java - 使用 NIO,我需要关心 block 边界上的 R/W 吗?

标签 java database-design nio memory-mapped-files

背景

在优化数据库设计方面做了大量工作,尤其是在从磁盘(包括主轴和 SSD)读取和写入数据的最佳方式领域。

从工作中得出的知识表明,在 block 边界上读取和写入,匹配您正在运行的文件系统的 block 大小,是最佳方法。

问题

假设我在一个内存相对较低的环境中运行,并且想使用一个 32MB 的内存映射小文件来读写一个 500GB 的巨大文件的内容。

如果我使用 Java 的 NIO 机制,特别是 MappedByteBuffer (Java 的内存映射文件机制),在配对我需要的数据之前,我是否需要注意在 block 边界(例如 4KB)上执行读和写操作到内存中,或者我可以在任何位置发出 R/W 操作我希望并允许操作系统、VM 分页逻辑、文件系统和存储固件处理操作优化并根据需要剔除我不需要的额外 block 数据?

其他详细信息

这个问题的原因是数据库设计,我看到这个痴迷专注于 block 优化,以至于似乎不存在一个你可以读写的世界没有 block 概念的数据。

让我感到困惑的是,文件系统是执行 block 操作单元的系统,那么为什么我的更高级别的应用程序需要担心这个呢?如果我想要偏移量 71 处的 17,631 个字节,我不能直接捕获它们并读入它们吗,或者我是否真的更快地弄清楚 读取操作从 block 0 开始,跨越 block 0、1 和 2 的边界...将所有这 3 个 block 读入内部字节 [],然后首先剔除我想要的 17,631 个字节?

如果关于数据库设计的文献对这个 block 的想法不是那么虔诚,我永远不会想到这个问题,但因为它是,我想知道我是否在这里遗漏了一个关键细节 WRT 文件系统和优化 block 设备 I/O。

感谢阅读。

最佳答案

我认为数据库知道 block 大小(可能与 fs block 大小不完全相同,但当然应该对齐)的部分原因不仅仅是为了执行 block 对齐的 I/O,而且管理磁盘数据在内存中的缓存方式,而不仅仅是依赖操作系统缓存。事实上,一些数据库完全绕过操作系统文件系统缓存。让数据库管理缓存有时可以更智能地了解缓存的使用方式,而操作系统可能无法提供。

rdbms 通常会考虑在查询期间可以读取/写入的 block 数,以便比较不同的执行计划:并且从同一 block 中获取所有数据的可能性可能是一种有用的优化注意。

我熟悉的大多数数据库都有 block 缓存/缓冲区的概念,数据库工作集的某些部分位于其中。管理完全由任意范围组成的缓存可能会更难管理。此外,许多数据库实际上将它们存储的数据安排为一系列 block ,因此 I/O 模式由此产生。当然,这可能只是最初为没有丰富操作系统缓存设施的平台编写的数据库的遗留问题......

尝试用对您的问题的某种答案来结束这篇漫谈……我的感觉是从映射文件中的任意范围读取并让操作系统处理额外的废料应该没问题。在性能方面,尝试让操作系统进行预读可能更重要:例如使用“建议”调用,以便操作系统可以在您处理当前范围时开始从磁盘读取下一个范围。当然,还有一种方法可以建议操作系统取消缓存您已完成的范围。

关于java - 使用 NIO,我需要关心 block 边界上的 R/W 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9141549/

相关文章:

mysql - 我应该在 MySQL 中使用标识号作为用户名吗?

java - 当我尝试在 android studio 中调试时卡在收集数据中

java - 反序列化json数组,其中属性值为数组java

c# - 用户可定制的数据结构的设计选择?

三个模型之间的Django关联

java - 对象解码期间发生 StreamCorruptedException

java - 如何使用 Files.getFileStore() 替换驱动器(在 Windows 上)?

Java:在巨大的磁盘文件上进行随机读取的最快方法

java - 无法执行目标 org.apache.maven.plugins :maven-archetype-plugin:2. 4:generate

java - Spring 启动 : "Scope ' request' is not active for the current thread"in Asynch method