有人能帮我了解硬盘寻道是如何工作的吗?
我有一个小的二进制数据库文件,它的读取性能是绝对必要的。如果我需要跳过文件中的几个字节,是使用seek()还是read()更快,然后丢弃不需要的数据。
如果硬盘的平均寻道时间是10ms,而读取速度是300MB/s,我计算出,值小于3MB的read()比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.或者使用first结构,当需要条目时,在末尾将seek()放入数据存储库。
条目为4字节,值为8字节,数据为12KB
干杯
发布于 2009-03-01 21:19:19
所有seek系统调用所做的就是更改文件中下一次读取的位置。它不会移动驱动器磁头。当读取或写入数据时,驱动器磁头会移动,您无法直接控制操作系统的下一步操作。
读取大量不需要的数据会产生影响,因为所有读取的数据都需要操作系统缓冲区中的空间,并导致较旧的数据被丢弃。因此,在大文件上使用查找将减少对文件系统缓存的干扰。
我在下面写的所有内容都假设你不能在内存中容纳整个数据库。如果可以的话,就这么做吧。读取所有内容,并尝试在文件末尾追加新的和更改的数据。不要担心浪费空间,只要偶尔做一些压缩即可。
如果您的数据库太大:
数据以块(或页)的形式读取和写入物理驱动器。类似地,操作系统中磁盘IO的基本单位是页。如果操作系统从磁盘缓存数据,那么数据也是整页的。因此,考虑是否需要使用seek或read向前移动几个字节是没有什么意义的。如果你想让它变得更快,你需要考虑磁盘IO是如何工作的。
首先,nobugz已经提到引用的局部性。如果您在每个操作中使用的数据在一个文件中靠得很近,您的操作系统将需要读取或写入较少的页面。另一方面,如果您分散数据,将需要一次读取或写入多个页面,这将总是很慢。
至于索引的数据结构。通常,它们被组织为B-trees。它是一种数据结构,专门用于通过分页读取和写入有效地搜索存储在内存中的大量数据。
这两种组织数据的策略都在实践中使用。例如,默认情况下,MS SQL Server以第一种方式存储数据:数据单独存储,索引仅包含文件中索引列和数据行的物理地址中的数据。但是如果您定义了聚集索引,那么所有数据都将存储在此索引中。所有其他索引将通过聚集索引键而不是物理地址指向数据。第一种方法更简单,但如果您经常基于聚集索引扫描数据范围,则另一种方法可能更有效。
发布于 2009-03-01 20:21:25
寻求访问的“绝对必要”有多重要?您是否使用非最佳解决方案测试过您的应用程序?在测试期间,您是否进行了基准测试以确定真正的瓶颈在哪里?如果你没有,你会对结果感到惊讶。
接下来,尝试不同的方法并比较运行时间。在不同的系统负载下进行测试(例如,当系统空闲时,除了您的应用程序外,当它繁忙时)。
考虑到,当新的、更快的硬盘具有不同的内部优化时,基于当前硬盘的优化可能会变得不正确,从而使您的工作付之东流。
发布于 2009-03-01 20:25:42
顺序读取总是比需要磁头查找(而不是位置查找)的读取更快。顺序读取的典型硬盘驱动器性能为50-60 MB/秒,寻求将其降至最坏情况下的约0.4 MB/秒。一旦定位了磁头,您基本上就可以免费获得柱面中的数据。文件系统缓存通过从柱面预读取扇区来利用这一点。
但是,您无法控制数据在磁盘柱面上的放置。你也猜不出驱动器的几何形状。请注意,当卷出现碎片时,吞吐量可能会随着时间的推移而明显变差。您需要通过在内存中缓存数据来查找perf。在这一点上,您需要担心locality of reference.
https://stackoverflow.com/questions/600400
复制相似问题