【发布时间】:2016-01-25 13:41:03
【问题描述】:
我在 Postgres 数据库中有一个缓慢的查询。使用explain analyze,我可以看到 Postgres 对两个不同的索引进行位图索引扫描,然后对两个结果集进行位图 AND。
删除其中一个索引会使评估速度提高十倍(位图索引扫描仍用于第一个索引)。但是,删除的索引在其他查询中很有用。
查询:
select
booking_id
from
booking
where
substitute_confirmation_token is null
and date_trunc('day', from_time) >= cast('01/25/2016 14:23:00.004' as date)
and from_time >= '01/25/2016 14:23:00.004'
and type = 'LESSON_SUBSTITUTE'
and valid
order by
booking_id;
索引:
"idx_booking_lesson_substitute_day" btree (date_trunc('day'::text, from_time)) WHERE valid AND type::text = 'LESSON_SUBSTITUTE'::text
"booking_substitute_confirmation_token_key" UNIQUE CONSTRAINT, btree (substitute_confirmation_token)
查询计划:
Sort (cost=287.26..287.26 rows=1 width=8) (actual time=711.371..711.377 rows=44 loops=1)
Sort Key: booking_id
Sort Method: quicksort Memory: 27kB
Buffers: shared hit=8 read=7437 written=1
-> Bitmap Heap Scan on booking (cost=275.25..287.25 rows=1 width=8) (actual time=711.255..711.294 rows=44 loops=1)
Recheck Cond: ((date_trunc('day'::text, from_time) >= '2016-01-25'::date) AND valid AND ((type)::text = 'LESSON_SUBSTITUTE'::text) AND (substitute_confirmation_token IS NULL))
Filter: (from_time >= '2016-01-25 14:23:00.004'::timestamp without time zone)
Buffers: shared hit=5 read=7437 written=1
-> BitmapAnd (cost=275.25..275.25 rows=3 width=0) (actual time=711.224..711.224 rows=0 loops=1)
Buffers: shared hit=5 read=7433 written=1
-> Bitmap Index Scan on idx_booking_lesson_substitute_day (cost=0.00..20.50 rows=594 width=0) (actual time=0.080..0.080 rows=72 loops=1)
Index Cond: (date_trunc('day'::text, from_time) >= '2016-01-25'::date)
Buffers: shared hit=5 read=1
-> Bitmap Index Scan on booking_substitute_confirmation_token_key (cost=0.00..254.50 rows=13594 width=0) (actual time=711.102..711.102 rows=2718734 loops=1)
Index Cond: (substitute_confirmation_token IS NULL)
Buffers: shared read=7432 written=1
Total runtime: 711.436 ms
我可以防止在 Postgres 中为特定查询使用特定索引吗?
【问题讨论】:
-
显示查询,显示解释。您不能禁用索引,但您可以对查询进行足够的更改,使其不会使用索引。
-
@jakub-kania 我想知道是否可以为特定查询禁用索引。你已经给我答案了。无论如何,我更新了我的问题并添加了查询、索引描述和查询计划。
-
我认为
booking_substitute_confirmation_token_key是您要“禁用”的那个? -
@jakub-kania 是的。顺便提一句。我只是尝试用
create unique index booking_substitute_confirmation_unique on booking(substitute_confirmation_token) where substitute_confirmation_token is not null替换索引,这样可以将评估时间从 711 加快到 10 毫秒。 -
好吧,我最终用唯一索引替换了唯一约束(和相关的默认索引
booking_substitute_confirmation_token_key),如我上面的评论所示。这对我来说似乎是一个完美的解决方案。此唯一索引不包括索引属性具有空值的行。该表有几百万行和几千行非空值。
标签: sql postgresql indexing query-optimization postgresql-performance