簡體   English   中英

什么是優化此SQL查詢的最佳方法

[英]What is the best way to optimize this sql query

我有以下SQL查詢,但是我注意到它給我的服務器帶來了壓力,因為每次運行它時,CPU使用率都會以20%的良好幅度躍升。

SELECT 
    c.name, c.billingaddress, c.billingcity, c.billingstate, c.billingzip,c.ifActive,
    (SELECT COUNT(l.id) FROM newLoads l WHERE l.idCompany = c.id AND l.smallStatus='1') as numberLoads,
    (SELECT (SUM(l.loadRate))/(SUM(l.esMiles)) FROM newLoads l WHERE l.idCompany = c.id AND l.loadRate != '0' AND l.esMiles != '0' AND l.smallStatus='1') as RPM
    FROM `companies` c WHERE ifContractor ='0' $cond
    ORDER BY numberLoads DESC

可能會更有效:

SELECT  c.name, c.billingaddress, c.billingcity,
        c.billingstate, c.billingzip, c.ifActive,
        x.numberLoads, x.RPM
    FROM  
      ( SELECT  l.idCompany,
                COUNT(*) AS numberLoads,
                SUM(l.loadRate))/(SUM(l.esMiles) AS RPM
            FROM  newLoads l
            WHERE  l.smallStatus = '1' 
      ) AS x
    JOIN  companies AS c  ON c.id = x.idCompany
    WHERE  ifContractor = '0' $cond
    ORDER BY  x.numberLoads DESC; 

請提供SHOW CREATE TABLEEXPLAIN SELECT ...

這是您的查詢:

SELECT c.name, c.billingaddress, c.billingcity, c.billingstate, c.billingzip, c.ifActive,
       (SELECT COUNT(l.id)
        FROM newLoads l
        WHERE l.idCompany = c.id AND l.smallStatus = '1'
       ) as numberLoads,
       (SELECT (SUM(l.loadRate))/(SUM(l.esMiles))
        FROM newLoads l
        WHERE l.idCompany = c.id AND l.loadRate <> '0' AND l.esMiles <> '0' AND l.smallStatus = '1'
       ) as RPM
FROM `companies` c
WHERE ifContractor = '0' $cond
ORDER BY numberLoads DESC;

我不知道$cond應該是什么。 它肯定不是有效的SQL語法,因此我將忽略它。

對於此查詢,您需要以下索引: companies(ifContractor, id)newload(idCompany, smallstatus, loadrate, esmiles, id)

順便說一句,如果其值看起來像數字的列實際上是數字,則請刪除單引號。 類型轉換會混淆優化器。

也許20%並不那么糟糕? (特別是如果只是短暫的爆發)從外觀上看,它可能需要處理大量數據才能獲得結果。

我試圖將newLoads表上的聚合合並到單個SELECT中,並最終得到(非常)類似於Rick James已經擁有的東西。 我的構造的另一個好處是,如果newLoads中沒有匹配的信息和/或當字段之一為零時,它與原始查詢更加一致。 (我認為,並沒有真正測試過)

SELECT c.name, c.billingaddress, c.billingcity, c.billingstate, c.billingzip, c.ifActive, agg.numberLoads, agg.RPM
FROM `companies` c
LEFT OUTER JOIN ( (SELECT l.idCompany,
                          numberLoads = COUNT(l.id),
                          RPM = (CASE WHEN SUM((CASE WHEN l.loadRate <> '0' AND l.esMiles <> '0' THEN 1 ELSE 0 END)) = 0 THEN NULL ELSE

                                    SUM((CASE WHEN l.loadRate <> '0' AND l.esMiles <> '0' THEN l.loadRate ELSE 0 END)) / SUM((CASE WHEN l.loadRate <> '0' AND l.esMiles <> '0' THEN l.esMiles ELSE 0 END)) 
                                        END)
                    FROM newLoads l
                   WHERE l.smallStatus = '1'
                   ) AS agg
             ON agg.idCompany = c.id 

WHERE c.ifContractor = '0' $cond
ORDER BY agg.numberLoads DESC;

無論如何,如果持續時間是一個問題,您可能要檢查是否在相關字段(如Gordon Linoff)上正確建議了(復合)索引,以及$cond可能包含的內容; 可能會知道正在執行哪種篩選以及它對查詢的整體性能有何影響。

PS:沒有太多的mysql實際經驗,我想知道l.esMiles <> '0'是否不比l.esMiles <> 0 “慢”,假設l.esMiles是一個數字字段(例如整數或十進制等。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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