可能有人会帮助我试图了解硬盘的搜索方式。

我有一个小的二进制数据库文件,读取性能绝对必要。如果我需要跳过文件中的几个字节,可以更快地使用seek()或read()然后丢弃不需要的数据。

如果硬盘的平均寻道时间是10ms,读取速度是300MB / s,我计算出读取()的速度比使用小于3MB的seek()要快。是真的?执行新搜索时是否存在开销,读取现有流没有?

您认为哪个是更合适的索引文件结构。

Entry1:Value:PointerIntoToData
Entry2:Value:PointerIntoToData
Entry3:Value:PointerIntoToData
Data, Data, Data

Or

Entry1:Value:Data
Entry2:Value:Data
Entry3:Value:Data

如果值不正确,当读取条目时,将忽略该条目。因此,当流式传输文件时,它更快: 1.当不需要输入时,使用seek()跳过它 2.当不需要输入时读取它然后丢弃数据 3.或者使用第一个结构,当一个条目需要seek()到最后的数据存储库时。

条目是4个字节,值是8个字节&数据为12KB

干杯

有帮助吗?

解决方案

所有搜索系统调用都会改变文件中下一次读取的位置。它不会移动驱动头。读取或写入数据时驱动器头会移动,而您无法直接控制下一步操作系统。

读取大量您不需要的数据会产生影响,因为所有读取数据都需要OS缓冲区中的空间并导致旧数据被丢弃。因此,使用seek over big files会减少文件系统缓存的负担。


我在下面写的所有内容都假设您无法将整个数据库放入内存中。如果可以的话,就这样做吧。读取所有内容并尝试在文件末尾附加新的和更改的数据。不要担心浪费空间,偶尔做一些压缩。


如果你的数据库太大了:

以块(或页)形式读取和写入数据到物理驱动器。同样,操作系统中磁盘IO的基本单元是页面。如果操作系统从磁盘缓存数据,它也在整个页面中。因此,考虑是否需要使用搜索或读取向前移动几个字节毫无意义。如果你想快速完成,你需要考虑磁盘IO的真正工作方式。

首先,nobugz已经提到过,参考地点。如果您在每个操作中使用的数据位于文件中,则操作系统将需要读取或写入较少的页面。另一方面,如果您传播数据,则需要一次读取或写入许多页面,这将始终很慢。

关于索引的数据结构。通常它们被组织为 B-trees 。它是一种数据结构,专门用于通过分页读写来有效搜索存储在内存中的大量数据。

这两种组织数据的策略都在实践中使用。例如,MS SQL Server默认以第一种方式存储数据:数据单独存储,索引仅包含索引列中的数据和文件中数据行的物理地址。但是,如果定义聚簇索引,则所有数据都将存储在此索引中。所有其他索引将通过聚簇索引键而不是物理地址指向数据。第一种方法更简单,但如果您经常根据聚集索引扫描数据范围,则另一种方法可能更有效。

其他提示

如何“绝对必要”寻求访问?您是否使用非最佳解决方案测试了您的应用程序?在测试期间,您是否进行了基准测试以确定真正瓶颈的位置?如果你还没有,你会对结果感到惊讶。

接下来,尝试不同的方法并比较运行时间。在不同的系统负载下进行测试(即系统处于空闲状态,除了您的应用程序以及繁忙时)。

考虑到当新的,更快的硬盘驱动器具有不同的内部优化功能时,基于当前硬盘驱动器的优化可能会变得不正确。

顺序读取总是比需要磁头搜索(而不是位置搜索)的读取更快。顺序读取的典型硬盘驱动器性能为50-60 MB /秒,寻求下降到最差情况~0.4 MB /秒。一旦驱动头定位,您基本上可以免费获取气缸中的数据。文件系统缓存通过预读取圆柱体中的扇区来利用它。

但是,您无法控制磁盘柱面上的数据放置。你也猜不到驱动器的几何形状。请注意,当卷碎片化时,吞吐量会随着时间的推移而显着变差。您需要通过在内存中缓存数据来查找perf。此时,您担心参考地点。

您始终可以将文件映射到内存中,然后通过指针等访问它。这通常应该使您的访问更简单

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top