[英]optimize given sql query for speed
我從一個程序員同事那里得到了這個查詢,但它執行得非常慢。 運行大約需要 4 秒鍾。
可以優化此查詢以提供相同的結果,但性能更好嗎?
SELECT checkedcrates,
pv.name as powervision,
cg.name as cgrp,
cs.name as csz,
c.name as cname
FROM public.inspectionresultsstatistic e,
crates c,
powervisions pv,
lines l,
quality q,
cratesgroupscrates cgc,
cratesgroups cg,
cratessizes cs
where
c.id = e.crateid
and l.id = e.lineid
and pv.id = l.powervisionid
and q.id = e.qualityid
and c.id = cgc.crateid
and cs.id = cgc.cratesizeid
and cg.id = cgc.crategroupid
and qualityid = 0
and pv.name in ('PV101')
and c.name in ('24603','104','136','154','186','106','156','216','246','206')
and cg.name in ('Black','Blue','DLL','Green')
and cs.name in ('30x40','60x40')
and to_timestamp(e.startts) >= '2021-10-18T17:45:22Z'
and to_timestamp(e.stopts-1) <= '2021-10-18T19:45:22Z'
group by
powervision,
cgrp,
csz,
cname,
checkedcrates,
startts
編輯:實際上只是注意到它是內部選擇緩慢......通過刪除外部查詢更新了上面的查詢
EDIT2:也許我應該添加一些索引? 我為每個表連接到另一個表(所以所有的 ID 列)都有一個索引,並且對檢查結果統計有一個關於 id + qualityid + startts + stopts 的索引
EDIT3:根據請求,我嘗試提供有關我的表和數據的更多信息。
我正在使用 PostgreSql 12,
表結構如下:
http://sqlfiddle.com/#!17/bb5a6/1
除了包含大約 12.000.000 行的檢查結果統計數據外,所有表都相當小,只有不到 50 個條目。
我的主要觀點是您的連接不是用更新的語法編寫的。 當您在 FROM 子句中的表之間使用逗號時,它會創建兩個表的“笛卡爾積”。 這比使用“INNER JOIN”后跟“ON”子句要占用更多資源。 應使用 ON 子句而不是 WHERE 子句中的約束。
類似的東西,
SELECT checkedcrates,
pv.name as powervision,
cg.name as cgrp,
cs.name as csz,
c.name as cname
FROM public.inspectionresultsstatistic e
INNER JOIN crates c
ON c.id = e.crateid
INNER JOIN lines l
ON l.id = e.lineid
INNER JOIN powervisions pv
ON pv.id = l.powervisionid
INNER JOIN quality q
ON q.id = e.qualityid
INNER JOIN cratesgroupscrates cgc
ON c.id = cgc.crateid
INNER JOIN cratesgroups cg
ON cg.id = cgc.crategroupid
INNER JOIN cratessizes cs
ON cs.id = cgc.cratesizeid
where qualityid = 0
and pv.name in ('PV101')
and c.name in ('24603','104','136','154','186','106','156','216','246','206')
and cg.name in ('Black','Blue','DLL','Green')
and cs.name in ('30x40','60x40')
and to_timestamp(e.startts) >= '2021-10-18T17:45:22Z'
and to_timestamp(e.stopts-1) <= '2021-10-18T19:45:22Z'
group by
powervision,
cgrp,
csz,
cname,
checkedcrates,
startts
你的小提琴不包括索引。 您應該使用 db-fiddle.com 而不是 sqlfiddle,因為后者基本上已損壞,沒有比 9.6 更新的內容。
被查詢的時間范圍非常小,所以大概是非常有選擇性的。
您最好將其作為一個范圍進行查詢:
and tstzrange(to_timestamp(e.startts),to_timestamp(e.stopts-1),'[]') <@
tstzrange('2021-10-18T17:45:22Z','2021-10-18T19:45:22Z','[]')
哪個將受益於表達索引
on inspectionresultsstatistic using gist (tstzrange(to_timestamp(startts),to_timestamp(stopts-1),'[]'))
但實際上,最好將時間戳存儲為 timestamptz 而不是 int8,或者甚至直接將它們存儲為 tstzrange。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.