簡體   English   中英

優化給定的 sql 查詢以提高速度

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM