对于相等性查找,哈希索引如何不快于Btree?


8

对于支持哈希索引的每个Postgres版本,都有警告或注意,至少在8.3版之前,哈希索引比btree索引“相似或更慢”或“不更好” 。从文档:

版本7.2

注意:由于哈希索引的用途有限,因此通常应优先选择B树索引而不是哈希索引。我们没有足够的证据表明即使进行=比较,哈希索引实际上也比B树更快。而且,散列索引需要更粗的锁。参见第9.7节。

版本7.3(以及最高8.2)

注意:测试表明PostgreSQL的哈希索引 B树索引相似或比B树索引,并且哈希索引的索引大小和构建时间要差得多。在高并发下,哈希索引的性能也很差。由于这些原因,不鼓励使用哈希索引。

版本8.3

注意:测试表明PostgreSQL的哈希索引的性能并不比B树索引好,并且哈希索引的索引大小和构建时间要差得多。此外,哈希索引操作目前还没有进行WAL记录,因此在数据库崩溃后可能需要使用REINDEX重建哈希索引。由于这些原因,目前不鼓励使用哈希索引。

他们声称在此版本8.0线程中,从未发现哈希索引实际上比btree更快的情况。

即使是在9.2版中,根据该博客文章(2016年3月14日):
AndréBarbosa撰写的Postgres哈希索引,除编写实际索引外,其他任何方面的性能提升也几乎没有。

我的问题是那怎么可能?

根据定义,哈希索引是一个O(1)操作,其中btree是一个O(log n)操作。那么,O(1)查找比查找正确的分支然后查找正确的记录要慢(或什至类似于)的可能性如何呢?

我想知道索引理论到底有什么可能!


Answers:


7

基于磁盘的Btree索引确实为O(log N),但这与适合此太阳系的磁盘阵列几乎没有关系。由于缓存,它们通常是常数很大的O(1)加上常数很小的O((log N)-1)。形式上,这与O(log N)是相同的,因为常量在大O表示法中无关紧要。但实际上它们确实很重要。

散列索引查找的速度下降大部分是由于需要防止由散列表的大小调整和查找所引起的损坏或死锁。在最新版本(您提到的每个版本都可笑地过时)之前,这种需求导致更高的常量和相当差的并发性。与散列并发相比,用于BTree并发优化的工时要多得多。


谢谢。我非常了解这些版本的过期日期有多久,但是我仍然对性能远远落后于我的预期感到好奇
Sampson Crowley

3

理论上,O(1)当键哈希直接映射到目标记录的物理位置时,哈希查找是一项操作。如果我正确理解的话,它在Postgres中的工作方式会更加复杂:键哈希映射到包含您要查找的OID 的存储桶。一个存储桶可能包含多个页面,您需要对其进行顺序扫描,直到找到您的特定密钥(哈希)为止。这就是为什么它看起来比您预期的慢。

源代码存储库中的哈希索引访问方法README文件包含所有详细信息。


因此就psql而言,哈希索引基本上是一种分支索引
Sampson Crowley,

知道他们使用存储桶来存储实际密钥实际上更加有意义
Sampson Crowley,

也感谢您提供自述文件的链接。我不知道在回购的存在
桑普森克劳利

2
确实需要对溢出页面进行线性搜索,在更坏的简并情况下,可能存在无限数量的溢出页面。但是页面内的搜索具有可在页面上存在的有限数量的项目,因此每个溢出页面的搜索量为O(1),并且它们使用二进制搜索,因此常量也不会太破旧。真正使瓶颈在于确保操作并发安全的规定。
jjanes

1
@AnoE-您会惊讶的是,性能和[浪费]资源之间总是需要权衡取舍;在某些情况下,可能会偏爱性能。
mustaccio
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.