Postgresql 为什么在同一个查询中忽略哈希索引而使用btree索引

Postgresql 为什么在同一个查询中忽略哈希索引而使用btree索引,postgresql,Postgresql,我认为这两种情况都只需要扫描索引,但事实并非如此。仅使用BTree索引 下面是一个例子 如果存在测试,则丢弃表格; 创建表测试 ( id serial4主键, 名称varchar(255)不为空, 分数int不为空 ); 我插入了1000000行。9867行分数为0 用散列索引解释 如果存在测试分数为零,则删除索引; 使用分数为0的哈希(id)在测试上创建索引测试分数; 解释分数为0的测试中的选择id; 用BTree索引解释 如果存在测试分数为零,则删除索引; 使用得分为0的btree(id

我认为这两种情况都只需要扫描索引,但事实并非如此。仅使用BTree索引

下面是一个例子

如果存在测试,则丢弃表格;
创建表测试
(
id serial4主键,
名称varchar(255)不为空,
分数int不为空
);
我插入了1000000行。9867行分数为0

用散列索引解释

如果存在测试分数为零,则删除索引;
使用分数为0的哈希(id)在测试上创建索引测试分数;
解释分数为0的测试中的选择id;
用BTree索引解释

如果存在测试分数为零,则删除索引;
使用得分为0的btree(id)在测试中创建索引测试得分为零;
解释分数为0的测试中的选择id;
哈希索引结果为

Gather  (cost=1000.00..13578.03 rows=9867 width=4)
  Workers Planned: 2
  ->  Parallel Seq Scan on test  (cost=0.00..11591.33 rows=4111 width=4)
        Filter: (score = 0)
Index Only Scan using test_score_zero on test  (cost=0.29..262.58 rows=9867 width=4)
BTree索引结果为

Gather  (cost=1000.00..13578.03 rows=9867 width=4)
  Workers Planned: 2
  ->  Parallel Seq Scan on test  (cost=0.00..11591.33 rows=4111 width=4)
        Filter: (score = 0)
Index Only Scan using test_score_zero on test  (cost=0.29..262.58 rows=9867 width=4)
PostgreSQL版本:

psql (PostgreSQL) 12.5 (Ubuntu 12.5-1.pgdg18.04+1)
哈希索引不支持“仅索引扫描”

为了解决这个性能问题,PostgreSQL只支持索引扫描[…]

索引类型必须支持仅索引扫描。B树索引总是这样。GiST和SP GiST索引只支持对某些运算符类进行索引扫描,而不支持对其他运算符类进行索引扫描其他索引类型不受支持

(强调矿山)


使用散列索引而不是B树索引的原因很少,如果您认为仅索引扫描将大大提高查询的性能,请坚持使用B树索引。

Hmm。但是为什么不使用普通索引扫描呢?但是如果您切换到普通索引扫描(通过选择“名称”而不是“id”),您仍然会得到与使用btree相同的行为,但哈希不是。还有其他原因导致这种行为,但我无法确定。所有的amcan*属性看起来都不相关,但可能其中有一个相关。