【问题标题】:Database Structure & Hard drive seek time confusion数据库结构和硬盘寻道时间混乱
【发布时间】:2010-10-10 16:00:48
【问题描述】:

有人可以帮助我了解硬盘搜索的工作原理吗?

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

如果硬盘的平均寻道时间为 10 毫秒,读取速度为 300MB/s,我计算出 read() 比值小于 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. 或者使用 first 结构,当一个条目需要 seek() 到最后的数据存储库时。

Entry 4 bytes,value 8 bytes & data 12KB

干杯

【问题讨论】:

    标签: c++ hardware hard-drive


    【解决方案1】:

    seek 系统调用所做的只是改变文件中下一次读取的位置。它不移动驱动头。当数据被读取或写入时,驱动器磁头会移动,并且您无法直接控制操作系统接下来会做什么。

    读取大量不需要的数据会产生影响,因为所有读取的数据都需要操作系统缓冲区中的空间,并导致旧数据被丢弃。所以在大文件上使用 seek 会减少文件系统缓存的混乱。


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


    如果您的数据库太大:

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

    首先,nobugz 已经提到,参考位置。如果您在每个操作中使用的数据在文件中的位置很接近,那么您的操作系统将需要读取或写入更少的页面。另一方面,如果您传播数据,则需要一次读取或写入许多页面,这总是很慢。

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

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

    【讨论】:

      【解决方案2】:

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

      接下来,尝试不同的方法并比较运行时间。在不同的系统负载下进行测试(即,当系统空闲时(除了您的应用程序)和忙碌时)。

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

      【讨论】:

      • 不,我还没有测试过这个程序,它还在寻找不同的文件结构。每毫秒都很重要,我对理论最大值感兴趣。那么你认为我需要一个工作测试环境来找出答案吗?硬盘驱动器可能承受另一个进程的负载。谢谢
      • 如果如您所说,每毫秒都很重要,请尝试将数据库读入内存。你说它很小(你引用 3M),所以它应该很容易适合你的系统内存。但是,您仍然必须确定速度是真实的还是想象的要求;即为什么你需要速度?
      • 我很少看到硬件特性对优化软件性能很有用,除非是在很短的时间内,而且只有在异常配置下。直到经过彻底的测试。硬件变化太快在“要尝试的事情”列表中上升。
      【解决方案3】:

      顺序读取总是比需要磁头查找(而不是位置查找)的读取要快。用于顺序读取的典型硬盘驱动器性能为 50-60 MB/秒,寻找将其降至最坏情况下约 0.4 MB/秒。一旦驱动头被定位,您基本上可以免费获得气缸中的数据。文件系统缓存通过从柱面预读取扇区来利用这一点。

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

      【讨论】:

      • 头部搜索和位置搜索有什么区别?在一个文件中,您不能假设圆柱体总是相邻的(ext3)?数据被分割成 32MB 的块单独读取,但是块的体积意味着它们不能一次全部缓存在内存中。
      • @unknown,您对硬盘的寻道机制和系统调用感到困惑。在实践中,调用 seek 可能会更好,因为调用读取不会产生太多的内存开销。但这取决于您的应用程序的具体情况。
      • @Bobby - 你的权利我很困惑。那么 seek() 系统调用不总是移动头部吗?仅当需要移动到另一个气缸时?
      • 当需要读取流来更改柱面时,是否会导致相同数据的 seek() 系统调用相同的惩罚?谢谢
      【解决方案4】:

      您总是可以将文件映射到内存中,然后通过指针等访问它。这通常会使您的访问更简单并且更快。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-16
        • 1970-01-01
        • 2016-01-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多