我的问题是关于在没有任何数据库或序列化框架的情况下,按偏移量访问专用文件中的数据.虽然教科书上说,建议按块访问数据,例如一次检索/刷新4KiB(或更大,取决于特定设备),但有时我对它的必要性感到困惑.

我见过许多数据库项目使用块感知设计来管理数据,例如从磁盘读取/写入数据一次,而不是实际请求的字节.

存储器/磁盘和系统缓冲区现在由操作系统/硬件控制,程序员不能直接控制块的移入/移出,尽管有FileDescriptor.sync()个.

因此,即使程序按块访问数据,这增加了复杂性,也可以通过OS机制消除该工作.相反,如果程序只使用偏移量访问数据,而不考虑块,底层操作系统可能会像往常一样帮助调度块检索.更不用说某些编程语言采用复杂的内存模型,可能会影响磁盘访问,比如Java.

我知道它对ACID的块/缓冲区管理很有帮助,但我想知道这种设计是否也是为了提高效率.

我搜索了网站,但没有得到任何线索.请注意一些关键词,我为我的无知感到抱歉.


虽然以下的答案已经解决了我的困惑,但我觉得我有责任把问题说得更清楚,使这个职位更切合社会需要.

我的困惑部分源于现有的开放文件格式,比如Parquet.但是,我看到它使用了可配置的固定长度页面,后面是一个碎片大小的头.我想知道这个文件是不是从一个块的开头就存储了,would the header make the following page splii a little over the block?因为页面占用一个块的大小.

再举个例子, 假设我正在构建一个数据库系统,使用Java.数据库使用特定的文件格式,由16 KiB的固定长度块组成.我的任务是实现对一个涉及大约FileChannel.write个字节的记录的更新.在已知记录位置的情况下,我可以直接用FileChannel.write写入(假设没有其他记录受到影响),或者检索整个块(供以后使用)并重写整个16 KiB.在这种特定的模式下,写入这FileChannel.write个字节是否比写入整个块更有效?

希望这篇文章能让文章更加合理.

推荐答案

在现代操作系统/硬件上按块访问数据值得吗?

也许吧 正如您所观察到的,通常在硬件级别、操作系统内核和用户空间中的应用程序下面都有缓冲,所有这些都是为了提高I/O性能. 特定应用程序是否可以从以块感知方式执行应用程序级I/O操作中受益取决于应用程序的数据访问模式.

应用程序级块感知的要点通常是减少必须在较低级别(尤其是硬件级别)执行的(面向块的)I/O操作的数量. 例如,如果我不小心设计数据库,我可能最终得到的主要 struct 通常跨越的磁盘块比它们所需要的大小要多. 尽管有所有缓冲,检索较少的块比检索较多的块要快. 以整个磁盘块为单位写入应用层数据也可以更快,因为这样系统就可以忽略目标块的初始内容. 否则,它必须首先读取其中一些块的内容,更新必须被重写的部分,然后才写入这些块.

我想知道这个设计是否也是为了提高效率?

您是对的,设计和实现硬件块大小的应用程序级容纳需要更多的工作量和更复杂. 除了I/O效率的原因外,一般不进行这种设计. 它们在这方面是否成功则是另一个问题,但对于设计为提供高I/O吞吐量的应用程序来说,此类设计仍然相对常见,这应该会让您认为是的,此类设计在这方面是有效的.

Java相关问答推荐

是否可以从@ TrustMapping中删除特定方法的基路径?

转换为Biggram

同时运行JUnit测试和Selenium/Cucumber测试时出现问题

为什么一个java函数会返回一个作为参数传递给它的对象?

为什么我的ArrayList索引的索引总是返回-1?

当我已经安装了其他版本的Java时,如何在Mac OSX 14.3.1上安装Java 6?

如何仅使用键/ID的一部分(组合)高效地返回映射值?

如何在太阳系模拟器中添加月球?

如何根据配置动态创建N个bean

如何在SWT菜单项文本中保留@字符

如何通过Java java.lang.Foreign API访问本机字节数组

为什么项目名称出现在我的GET请求中?

在Java中将对象&转换为&q;HashMap(&Q)

如何在Maven Central上部署?

具有多个分析模式的复杂分隔字符串的正则表达式

控制器建议异常处理

Java中的一个错误';s stdlib SocksSocketImpl?

如何在MPAndroidChart中的条形图上正确添加标签

如何显示新布局

@此处不能应用可为null的批注