我即将理解这一点,但我不明白我需要的修复。以下查询大约需要一分钟(给予或接受)来返回 20 条记录:
explain (analyze, buffers)
select "search_docket"."id"
FROM "search_docket"
WHERE "search_docket"."court_id" = 'delctcompl'
ORDER BY "search_docket"."id" desC
LIMIT 20;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.56..2791.05 rows=20 width=4) (actual time=74.950..41059.055 rows=20 loops=1)
Buffers: shared hit=38524709 dirtied=10
-> Index Scan Backward using search_docket_pkey on search_docket (cost=0.56..8837737.95 rows=63342 width=4) (actual time=74.947..41059.022 rows=20 loops=1)
Filter: ((court_id)::text = 'delctcompl'::text)
Rows Removed by Filter: 41862720
Buffers: shared hit=38524709 dirtied=10
Planning time: 0.450 ms
Execution time: 41059.233 ms
翻转排序顺序大约需要 60 毫秒:
explain (analyze, buffers)
select "search_docket"."id"
FROM "search_docket"
WHERE "search_docket"."court_id" = 'delctcompl'
ORDER BY "search_docket"."id" asC
LIMIT 20;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.56..2791.05 rows=20 width=4) (actual time=63.701..63.939 rows=20 loops=1)
Buffers: shared hit=45783
-> Index Scan using search_docket_pkey on search_docket (cost=0.56..8837737.95 rows=63342 width=4) (actual time=63.698..63.933 rows=20 loops=1)
Filter: ((court_id)::text = 'delctcompl'::text)
Rows Removed by Filter: 67080
Buffers: shared hit=45783
Planning time: 0.426 ms
Execution time: 63.971 ms
你可以看到,在第一个中,它在这里变得很糟糕:
Rows Removed by Filter: 41862720
Buffers: shared hit=38524709 dirtied=10
以下是表上的索引(省略与此查询无关的索引):
Indexes:
"search_docket_pkey" PRIMARY KEY, btree (id)
"search_docket_7a46e69c" btree (court_id)
"search_docket_court_id_2d2438b2594e74ba_like" btree (court_id varchar_pattern_ops)
杂念:
法院列的基数非常低。它在大约 50M 行中有大约 500 个值。
我想我可以在 上添加一个降序索引
court_id
,也许可以解决它,但这似乎不对。也许我需要一个多列索引
search_docket.id
和search_docket.court_id
?好像没了
我应该在这里做一些更好的事情来使索引更好地工作吗?
这些查询的理想选择是在索引中
(court_id, id)
,并且列按该顺序排列。它在任何一个方向上都应该非常快。一旦你拥有它,你应该能够摆脱 court_id 上的普通索引,因为它不再那么好了。满足条件的行(估计在 63000 左右)都有一个高
id
. PostgreSQL 不知道这一点,因此它认为索引扫描在任一方向上都同样具有吸引力。如果您知道它总是这样,请使用
DESC
. 如果不是,并且您希望避免对该索引进行索引扫描,请更改ORDER BY
子句以使其与索引表达式不匹配,例如通过添加+ 0
.