postgresql - 为什么在同一个查询中,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 支持仅索引扫描 [...]
索引类型必须支持仅索引扫描。B-tree 索引总是如此。GiST 和 SP-GiST 索引支持仅对某些运算符类进行索引扫描,但不支持其他运算符。其他索引类型不支持。
(强调我的)
使用散列索引而不是 B-Tree 索引的原因很少,如果您希望 Index Only Scan 能极大地帮助您的查询性能,那就坚持使用 B-Tree 索引。
推荐阅读
- javascript - 当我点击它时按钮消失了
- reactjs - 在 React Native 中回退退出前显示提示
- java - 有人可以解释一下这段代码是如何编译的
- mips - 用户输入“他很好”,我应该如何打印出 3 个单词和 9 个字母,而不是多次打印不同的值?
- reactjs - 运行“放大模拟”会重置对查询、突变的更改
- svg - 可以缩放独立的 .svg 以适应浏览器窗口吗?
- php - 如何在 Laravel 中将产品图像存储在单独的表中
- certificate - 如何在 AWS Certificate Manager 中导入 .pfx 证书?
- html - 单击按钮时打开 v-select 选项
- c++ - 在 sfml 中抛出“std::bad_alloc”实例后调用终止