繁体   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