首页 > 解决方案 > 为什么在同一个查询中,hash索引被忽略而使用btree索引

问题描述

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

下面是一个例子

drop table if exists test;

create table test
(
    id    serial4 primary key,
    name  varchar(255) not null,
    score int          not null
);

我插入了 1,000,000 行。9867 行得分为 0。

用哈希索引解释

drop index if exists test_score_zero;
create index test_score_zero on test using hash (id) where score = 0;
explain select id from test where score = 0;

用 BTree 索引解释

drop index if exists test_score_zero;
create index test_score_zero on test using btree (id) where score = 0;
explain select id from test where score = 0;

哈希索引结果是

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)

BTree 索引结果是

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

解决方案


如手册中所述,哈希索引根本不支持“仅索引扫描”

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

索引类型必须支持仅索引扫描。B-tree 索引总是如此。GiST 和 SP-GiST 索引支持仅对某些运算符类进行索引扫描,但不支持其他运算符。其他索引类型不支持

(强调我的)

使用散列索引而不是 B-Tree 索引的原因很少,如果您希望 Index Only Scan 能极大地帮助您的查询性能,那就坚持使用 B-Tree 索引。


推荐阅读