[英]Optimize SQL query with subquery on same table
我有以下 PostgreSQL
EXPLAIN (ANALYZE, BUFFERS) select h.pk::varchar(255),
(
h.fecha at TIME zone 'Mexico/General' at TIME zone 'UTC'
)::date as fecha
from historial h
where (
h.fecha at TIME zone 'Mexico/General' at TIME zone 'UTC'
)::date < '2022-07-30'
and h.del = 0
and (
select COUNT(h.pk)
from historial h
where h.tipo in (3, 6, 9, 10)
and h.del = 0
) > 10
order by h.fkcr,
h.fecha asc
但是歷史表有數百萬行,使用ORDER BY
子句會導致時間從 ~300ms 跳轉到 ~6000ms!
是否可以對其進行優化?
這是命令的EXPLAIN (ANALYZE, BUFFERS)
我注意到排序節點正在使用磁盤對其進行排序,所以我嘗試將work_mem
更改為 1GB,但它仍然使用磁盤,如果work_mem
已經工作或者我誤解了 work_mem 的work_mem
QUERY PLAN |
------------------------------------------------------------------------------------------------------------------------------------------------+
Sort (cost=215616.65..217123.46 rows=602724 width=40) (actual time=11770.953..13789.063 rows=1810355 loops=1) |
Sort Key: h.fkcr, h.fecha |
Sort Method: external merge Disk: 145136kB |
Buffers: shared hit=16461 read=49282, temp read=32832 written=32832 |
InitPlan 1 (returns $0) |
-> Aggregate (cost=48588.68..48588.69 rows=1 width=16) (actual time=479.485..479.486 rows=1 loops=1) |
Buffers: shared hit=441 read=24000 |
-> Bitmap Heap Scan on historial h_1 (cost=3146.86..48088.10 rows=200230 width=16) (actual time=26.643..357.554 rows=186103 loops=1)|
Recheck Cond: (tipo = ANY ('{3,6,9,10}'::integer[])) |
Filter: (del = 0) |
Rows Removed by Filter: 21311 |
Heap Blocks: exact=23863 |
Buffers: shared hit=441 read=24000 |
-> Bitmap Index Scan on idx_tipo (cost=0.00..3096.80 rows=208414 width=0) (actual time=22.107..22.107 rows=207414 loops=1) |
Index Cond: (tipo = ANY ('{3,6,9,10}'::integer[])) |
Buffers: shared hit=9 read=569 |
-> Result (cost=0.00..92681.53 rows=602724 width=40) (actual time=479.802..7149.979 rows=1810355 loops=1) |
One-Time Filter: ($0 > 10) |
Buffers: shared hit=16453 read=49282 |
-> Seq Scan on historial h (cost=0.00..83640.67 rows=602724 width=40) (actual time=0.293..2781.099 rows=1810355 loops=1) |
Filter: ((del = 0) AND ((timezone('UTC'::text, timezone('Mexico/General'::text, fecha)))::date < '2022-07-30'::date)) |
Rows Removed by Filter: 71719 |
Buffers: shared hit=16012 read=25282 |
Planning time: 1.105 ms |
Execution time: 14991.655 ms |
對於流程字段轉換或對字段進行任何操作,數據庫不能使用索引。 為此建議創建表達式索引。 例如:
CREATE INDEX historial_idx1 ON historial ((fecha at TIME zone 'Mexico/General' at TIME zone 'UTC'))
或者
CREATE INDEX test_idx1 ON test ((id::text))
建議為此字段創建索引:
並建議對子查詢使用物化 CTE,例如:
with subquery as materialized (
select COUNT(h.pk)
from historial h
where h.tipo in (3, 6, 9, 10)
and h.del = 0
)
select h.pk::varchar(255),
(
h.fecha at TIME zone 'Mexico/General' at TIME zone 'UTC'
)::date as fecha
from historial h
where (
h.fecha at TIME zone 'Mexico/General' at TIME zone 'UTC'
)::date < '2022-07-30'
and h.del = 0
and (select * from subquery) > 10
order by h.fkcr,
h.fecha asc
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.