2009-03-01 48 views
3

有人可以帮助我理解寻求硬盘驱动器的工作原理。数据库结构和硬盘驱动器寻找时间混淆

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

如果硬盘驱动器的平均寻道时间是10ms,读取速度是300MB/s,我计算出它比seek()小于3MB的读取速度更快。是真的?执行新的查找时是否有开销,读取现有的流时没有?

你认为哪种索引更合适的文件结构?

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

干杯

回答

4

全部查找系统调用确实正在改变下一次读取文件的位置。它不会移动驱动器头。读取或写入数据时驱动器磁头会移动,而您无法直接控制下一步操作系统的操作。

读取大量不需要的数据会产生影响,因为所有读取的数据都需要OS缓冲区中的空间,并导致旧数据丢失。因此,使用查找大文件将会导致文件系统缓存更少。


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


如果你的数据库是太大了:

数据读取和块(或页)写入到物理驱动器。同样,操作系统中磁盘IO的基本单位是页面。如果操作系统从磁盘缓存数据,它也在整个页面中。因此,考虑是否需要使用seek或read来向前移动几个字节是没有意义的。如果你想让速度更快,你需要考虑磁盘IO是如何工作的。

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

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

在实践中使用组织数据的两种策略。例如,默认情况下,MS SQL Server以第一种方式存储数据:数据单独存储,索引仅包含来自索引列的数据和文件中数据行的物理地址。但是如果你定义了聚集索引,那么所有的数据都将被存储在这个索引中。所有其他索引将通过聚簇索引键而不是物理地址指向数据。第一种方法比较简单,但如果您经常基于聚集索引扫描一系列数据,则其他方法可能会更加有效。

3

如何 “绝对必要的”,是寻求获得?您是否使用非最佳解决方案测试了您的应用程序?在测试期间,您是否通过基准测试来确定哪些是瓶颈?如果你还没有,你会对结果感到惊讶。

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

如果新的更快的硬盘具有不同的内部优化功能,将您的工作排除在外,请考虑基于当前硬盘的优化可能会不正确。

+0

不,我还没有测试过程序,它仍在研究不同的文件结构。每毫秒都很重要,我对理论最大值感兴趣。那么你认为我需要一个可用的测试环境吗?硬盘驱动器可能来自另一个进程的负载。谢谢 – user72523 2009-03-01 20:32:23

+0

如果您按照您的声明,每毫秒计数一次,请尝试将数据库读入内存。你说它很小(你引用3M),所以应该很容易适合你的系统内存。 但是,您仍然必须确定速度是否是真实或想象的要求;即为什么你需要速度? – 2009-03-01 20:41:29

1

顺序读取总是比需要头部搜索(不是位置搜索)的要快。顺序读取的典型硬盘驱动器性能为50-60 MB /秒,寻求下降至最差情况〜0.4 MB /秒。一旦驱动头定位后,您就可以免费获取气缸中的数据。文件系统缓存利用了预读气缸中的扇区的优势。

但是,您无法控制数据在磁盘柱面上的位置。你也不能猜测驱动器的几何形状。请注意,当卷被碎片化时,吞吐量会随着时间的推移而变得更糟。您需要通过在内存中缓存数据来查找perf。此时,您担心locality of reference.

0

你总是可以将文件映射到内存中,然后通过指针等进行访问。这通常应使您的访问速度更快,更简单