背景
在优化数据库设计方面已做了大量工作,特别是在从磁盘(主轴和SSD)读取和写入数据的最佳方式领域。
从工作中获得的知识表明,在块边界上读取和写入,与正在运行的文件系统的块大小相匹配,是最佳方法。
问题
假设我在相对较低内存的环境中运行,并希望使用一个小的32MB内存映射文件来读取和写入一个巨大的500GB文件的内容。
如果我使用的是Java的NIO机制,特别是MappedByteBuffer(Java的内存映射文件机制),在配对之前,我是否需要注意在块边界(例如4KB)上执行READ和WRITE操作我需要的数据,或者我可以在我想要的任何位置发出R / W操作,并允许操作系统,VM分页逻辑,文件系统和存储固件处理操作的优化和剔除我没有的其他块数据根据需要需要吗?
其他详细信息
问题的原因在于数据库设计,我看到 obsessive 专注于块优化,以至于似乎不存在一个你永远只会读写的世界没有块概念的数据。
令我困惑的是文件系统是强制执行块操作的单元,为什么我的更高级别的应用程序需要担心呢?如果我想要偏移71处的17,631个字节,我不能只抓住它们并读取它们,或者我真的更快找出它 读取操作从块0开始,落在块0,1和2的边界上...将所有这3个块读入内部字节[],然后首先剔除我想要的17,631个字节? / p>
如果关于数据库设计的文献对于这个块概念并不那么虔诚,那么这个问题就永远不会出现在我的脑海中,但是因为它是,我想知道我是否错过了WRT文件系统和最优的关键细节阻止设备I / O.
感谢您的阅读。
答案 0 :(得分:2)
我认为部分原因数据库可以识别块大小(可能与fs块大小不完全相同,但当然应该对齐)不仅仅是执行块对齐I / O,而且管理磁盘数据如何缓存在内存中,而不仅仅依赖于操作系统缓存。事实上,有些数据库完全绕过OS文件系统缓存。让数据库管理缓存有时可以更好地了解操作系统可能无法提供的缓存方式。
rdbms通常会考虑在查询期间可以读取/写入的块数,以便比较不同的执行计划:并且从同一块中获取所有数据的可能性可能是有用的优化注意到。
我熟悉的大多数数据库都有块缓存/缓冲区的概念,其中数据库的某些部分工作集存在。管理完全由任意扩展区组成的缓存可能会更难管理。此外,许多数据库实际上将它们存储的数据作为一系列块进行排列,因此I / O模式不断增长。当然,这可能仅仅是最初为没有丰富的OS缓存设施的平台编写的数据库的遗产......
尝试用你的问题的某种答案来结束这种漫游......我的感觉是从映射文件中的任意范围读取并让操作系统处理额外的slop应该没问题。在性能方面,尝试让操作系统进行预读更为重要:例如使用“建议”调用,以便操作系统可以在处理当前操作系统时从磁盘读取下一个范围。当然,这是一种建议操作系统解除您已完成的范围的方法。
答案 1 :(得分:2)
4KB块非常重要,因为它通常是MMU的粒度,因此也就是OS虚拟内存管理器的粒度。当项目经常一起使用时,设计数据库布局非常重要,这样这些项目最终会在同一页面中。这样,页面错误将在页面中的所有项目中进行分页。