我有一个带有主键和btree_gist索引的巨大表格。当我查询btree_gist索引中的列时,我会期望使用该索引并且查询执行速度很快。然而,优化器总是在主键和过滤器上执行索引扫描。
示例:
create table test1 (
id1 bigint not null,
id2 bigint not null,
validtime tstzrange not null,
data float);
alter table test1 add constraint pk_test1 primary key (id1, id2, validtime);
alter table test1 add constraint ex_test1_validtime exclude using gist (id1 with =, id2 with =, validtime with &&);
这张表包含大约12亿行数据,我想查询的结果只返回几百行,但是所需的时间很长:
select * from test1 where id1=1 and id2=1 and validtime && '[2020-01-01,2020-02-01)';
(about 3s)
查询计划:
explain select * from test1 where id1=1 and id2=1 and validtime && '[2020-01-01,2020-02-01)';
QUERY PLAN
-------------------------------------------------------------------------------------------
Index Scan using pk_test1 on test1 (cost=0.70..24.68 rows=1 width=46)
Index Cond: ((id1 = 1) AND (id2 = 1))
Filter: (validtime && '["2020-01-01 00:00:00+00","2020-02-01 00:00:00+00")'::tstzrange)
性能不佳的原因显然是在时间条件下读取和过滤了成千上万行。
我想知道为什么Postgres不使用btree_gist。
我有另一个略有不同的表,在这个表中,btree_gist被使用,但方式与我的预期非常不同。该表有大约1.6亿行。
create table test2 (
id1 bigint not null,
validtime tstzrange not null);
alter table test2 add constraint pk_test2 primary key (id1, validtime);
alter table test2 add constraint ex_test2_validtime exclude using gist (id1 with =, validtime with &&);
在这里,执行计划看起来是这样的:
select * from test2 where id1=1 and validtime && '[2020-01-01,2020-02-01)';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on test2 (cost=1933.19..1937.20 rows=1 width=62)
Recheck Cond: ((id1 = 1) AND (validtime && '["2020-01-01 00:00:00+00","2020-02-01 00:00:00+00")'::tstzrange))
-> BitmapAnd (cost=1933.19..1933.19 rows=1 width=0)
-> Bitmap Index Scan on pk_test2 (cost=0.00..574.20 rows=11417 width=0)
Index Cond: (id1 = 1)
-> Bitmap Index Scan on ex_test2_validtime (cost=0.00..1358.74 rows=17019 width=0)
Index Cond: (validtime && '["2020-01-01 00:00:00+00","2020-02-01 00:00:00+00")'::tstzrange)
为什么需要两个位图索引扫描?使用btree_gist索引一次性扫描不行吗?
EXPLAIN (ANALYZE, BUFFERS)
输出。关于您的第一个查询:如果您删除另一个索引,是否使用所需的索引? - Laurenz Albe