我有一个应用程序使用大量数据(100 GB+)存储在ESENT中。表的模式是:12字节的bitColumnFixed键和coltypLongBinary值,其典型大小约为2 KiB。页面大小设置为32 KiB。对于外部长值,我不更改默认的1024字节大小阈值,因此我认为这些值大多是外部存储的。
我对改进冷缓存查找和检索性能感兴趣,因为操作是批量进行的,而且密钥是预先知道的。据我所知,JetPrereadKeys() API旨在提高这种情况下的性能,但事实证明,无论是否使用此调用,都不会在实际行为中看到任何更改。
详情如下:
问题:
发布于 2020-01-15 22:50:44
JetPrereadKeys() API确实对叶级的父级进行同步读取,然后为所需的键/记录...I认为答案#2所需的所有叶页排队异步IOs。如果您的主表记录(注意,突发长值/ LVs存储在单独的树中)是浅的或完全缓存的,则此JetPrereadKeys()可能没有帮助。但是,如果表上的主树很大而且很深,那么这个API可以极大地帮助.它只取决于您正在检索的数据的形状和扩展。您可以通过转储空间、查看树的深度和获取“数据”页面的含义来了解有关您的表的一些基本知识,我是否可以建议:
esentutl /ms Your.Db /v /fName,Depth,Internal,Data列出表名、深度、内部页数和叶级数据页数。表名将为主记录树列出单独的行,然后在其下面列出LV/ as“长值”。
还请注意,这个预读键不会扩展到突发LVs .因此,如果您立即读取一个突发LV列-不幸的是,您会在IO后面。
默认模式是ESE分配和控制它自己的数据库缓冲区/页缓存。JET_paramEnableFileCache主要用于(通常是较小的)客户端进程,这些进程退出(或至少退出JetTerm/JetDetach其DB)并重新启动大量.所以ESE的私有缓冲区缓存在每次退出时都会丢失.但是JET_paramEnableFileCache是一个param,所以如果数据最近退出的话,它们可能仍然在文件缓存中。但是,不建议对大型DBs进行缓存,因为这会导致在ESE缓冲区缓存和NTFS / ReFS文件缓存中双缓存数据。JET_paramEnableViewCache增强了前面的param,并在一定程度上改进了这种双重缓存.但是它只能在干净/未修改的页面缓冲区上节省内存/不能双缓冲。对于大DBs,请将这两个参数分开/假。此外,如果您不使用这些参数,那么它更容易测试冷的perf .在你的应用程序退出(清除高清缓存)之后,只要在你的硬盘上拷贝一个大文件(100 MB,可能是1或2GB),你的数据就会变冷。;-)
既然我们已经提到了缓存..。最后一件事--我认为这可能是你的实际问题(如果不是我上面提到的“数据的形状”).打开perfmon并找到“数据库”和/或“数据库==>实例”perf对象(这些对象用于ESENT),查看缓存大小为“数据库缓存大小”或“数据库缓存大小(MB)”,并查看可用池/“数据库缓存%可用”的大小。当然,你必须用这个%对你的数据库缓存大小做数学来得到一个想法.但如果这个值很低这可能是你的问题..。这是因为JetPrereadKeys将只使用已经可用的缓冲区,因此您必须有一个健康/足够大的可用池。将JET_paramCacheSizeMin增大为更大,或将JET_paramStartFlushThreshold / JET_paramStopFlushThreshold设置为将可用缓存保持在缓存总大小的更大%.注意,它们被设置为与JET_paramCacheSizeMax成比例,因此类似于设置:
paramCacheSizeMin = 500
paramCacheSizeMax = 100000
paramStartFlush.. = 1000
paramStopFlushT.. = 2000这意味着您的开始和停止阈值分别为当前缓存大小的1%和2%,不管它是什么。因此,如果缓存在500个缓冲器(最小),5和10将是您的开始/停止阈值-即您的可用池将在范围内,如果它以后增长到10000缓冲区,那么您的可用池将在100到200个缓冲器之间。无论如何,您希望这些数字足够好,以便为JetPrereadKeys可能需要的所有叶页提供足够的缓冲区。
我没有在这封邮件里解释每一个术语,因为你看上去很高级的B树内部节点.但是如果有什么不清楚的话,只要问一问,我就把它弄清楚。
谢谢,
布雷特·雪莉
可扩展存储引擎开发人员
这个帖子是“原样”提供的,没有任何保证,也没有授予任何权利。
P.S. -你可能喜欢玩的最后一件事: JetGetThreadStats / JET_THREADSTATS,它告诉你一些我们在API下所做的内部操作。您基本上读取了前后的值和JET,并减去它们以获得该JET的操作#。所以你会看到cPagePreread在里面..。这将是一个很好的方法,可以查看JetPrereadKeys是否正在分发异步IOs,这将有助于perf。请注意,在一个旧的操作系统中,特别的计数器不幸被打破,但我不记得它是什么时候被破坏和修复的.win7呼叫win8,win8呼叫win8.1。如果您使用的是Win10,那么到那时它肯定没有问题。同时,cPageRead也是同步读取页(内部节点可能向上).我想您会发现这些对于各种JET API的成本非常有指导意义。
https://stackoverflow.com/questions/59752368
复制相似问题