与数据库索引的写入相比的读取数

时间:2016-12-23 14:18:07

标签: database indexing

众所周知,如果您有大型表并且读取次数多于写入,则数据库索引才有意义,因为索引的创建会导致额外的写入开销,因为数据库中的每个修改也会导致索引的修改。

如果我们假设数据库的索引结构是 a)B +树 b)哈希表 读取次数与实现数据库索引开始有意义的写入次数相比,经验法则是什么?

有关数据库索引如何工作的信息,请查看How does database indexing work?

3 个答案:

答案 0 :(得分:2)

这里涉及很多因素。例如,缓存中的索引数据是?缓存中的数据块是什么?查询检索了多少行?桌子上有很多行等等  我多次被问过这个问题(或其变体)。我不愿提供数字,而是提供一些信息,以便提出问题的人可以做出明智的决定。这是信封的背面"具有一些陈述假设的计算示例。

  1. 假设该表有100M行
  2. 假设一行平均为200字节
    • 表示表消耗大约19GB(忽略任何压缩)
  3. 让我们假设索引已完全缓存并且时间为零
  4. 让我们假设必须从磁盘读取数据,每次读取5ms
  5. 让我们假设您的IO子系统可以以10 GB / s的速度提供数据
  6. 让我们假设您需要从表中读取50,000行。让我们假设这些行是分散的,这样两行所需的行就存在于同一个块中。

    好的,现在我们可以做一些数学。

    场景1.使用索引

    • 索引读取为零时间
    • 数据块读取:25,000块@ 5ms,每块为125秒

    场景2.扫描表

    • 以10GB / s扫描的19GB是2s

    因此,在这种情况下,扫描数据要比使用索引快得多。

答案 1 :(得分:2)

费用公式

没有

  • insert:O(1)
  • 搜索O(n)
  • 成本搜索= n db查找操作
  • cost insert = db insert

a)b阶b +树

  • insert:O(log n)
  • 搜索:O(log n)
  • 费用搜索= log_b n查找操作+数据库查找
  • cost insert = log_b n lookup operations + db insert
  • 随着顺序的增加,查找操作的数量会减少,但每次查找操作的成本会增加

b)Hashtable

  • insert:O(1)
  • 搜索:O(1)
  • 成本搜索=哈希计算[发生冲突时+额外的桶] + db lookup
  • 成本插入=哈希计算[发生碰撞时+额外的桶] + db insert

n = 1000时的费用

没有

  • 成本搜索= 1000 db查找操作
  • 成本插入= 1 db insert

a1)2阶B +树

  • 成本搜索= 10次查找操作+ 1次db查找
  • 成本插入= 10个查找操作+ 1个数据库插入

a2)订单10的B +树

  • 成本搜索= 3次查找操作+ 1次db查找
  • 成本插入= 3次查找操作+ 1 db插入

b)Hashtable

  • 成本搜索=哈希计算[发生冲突时+额外的桶] + db lookup
  • 成本插入=哈希计算[发生碰撞时+额外的桶] + db insert

n = 1000000时的费用

没有

  • 成本搜索= 1000000 db查找操作
  • 成本插入= 1 db insert

a1)2阶B +树

  • 成本搜索= 20次查找操作+ 1次db查找
  • 成本插入= 20个查找操作+ 1个数据库插入

a2)订单10的B +树

  • 成本搜索= 6次查找操作+ 1次db查找
  • 成本插入= 6次查找操作+ 1次插入

b)Hashtable

  • 成本搜索=哈希计算[发生冲突时+额外的桶] + db lookup
  • 成本插入=哈希计算[发生碰撞时+额外的桶] + db insert

通过为随后的点击命中硬件缓存,可以获得相当大的成本收益。确切的收益取决于您的数据库安装的硬件。

成本并非易于比较。哈希计算通常比查找更昂贵,但随着n变大,它保持不变。 B树查找和顺序DB查找可能会遇到硬件缓存(由于加载了整个块)。

表越大,获得索引就越重要(参见n = 1000和n = 1000000的成本)。因此,写入与读取的数量将随着表的大小而变化。

您还应该考虑具体的问题。例如,在B树的情况下,不会对哈希表进行排序。因此,如果查询需要获取最小值和最大值之间的所有值,则B树的性能优于散列表(良好的散列均匀分布)。

通常,您必须衡量在实践中使用的查询和插入的性能。您可以在没有索引的情况下启动,然后在需要时添加一个索引。可以在以后添加索引,而无需使用数据库更改程序的查询(但查询的响应时间会发生变化,如果使用索引,读取速度会变快,写入速度会变慢)。

如果您处于加载操作且具有大量插入后跟一段读取的特定情况,您可以暂时关闭索引并在加载后重新计算它。

参考文献:

B树与哈希表:

https://cs.stackexchange.com/questions/270/hash-tables-versus-binary-trees

高速缓存

http://www.moreprocess.com/devices/computer-memory-hierarchy-internal-register-cache-ram-hard-disk-magnetic-tape

答案 2 :(得分:1)

使用数据库的关键通常是减少在数据中查找内容所花费的时间,因此它是关于"阅读"。我非常确定90%的人使用数据库来阅读"如果不是100%。

让我们想起几个案例:

  • 只写,不读:重点是什么?只是为了备份?好吧, 备份将在恢复时用于读取。
  • 许多写作,很少读取:我无法想到这种情况,但是当你遇到这种情况时,你更重视哪一个?迅速提出数据?或者您保存数据的速度有多快?如果您重视数据的保存速度,那么您可以删除索引并进行夜间运行以显示数据(我确定它足够大,需要夜间运行来总结数据,考虑到速度有多快数据正在被保存),因此你有近乎实时的写入,以及H + 1或更多的后期数据读取,这引起了质疑:具有这种配置的重点是什么?
  • 少量写入,多次读取:这是最常见的情况
  • 没有写入,只有读取:100%你不能产生这种情况,没有写入然后要读什么?

对不起我的英语,希望有所帮助