如何解决使用COUNT的子查询使MYSQL查询变慢
| 是的,我不知道为什么,但是此查询需要花费6秒钟以上的时间来执行,索引都已正确设置,如果我分别运行每个查询,它只需不到0.5秒钟的时间就可以很好地工作。 这是查询SELECT c.supplier_id,supplier_name,address1,address2,address3,address4,suppliertype,postcode,contact_name,(SELECT COUNT(*)
FROM supplier_questions q1
WHERE c.supplier_id = q1.supplier_id AND q1.incomplete = \'0\') AS questions,IF (active=1,\'Yes\',IF (active=2,\'NCR Only\',\'Inactive\')) AS rated,(SELECT COUNT(*)
FROM supplier_questions q2
WHERE c.supplier_id = q2.supplier_id AND q2.reviewed = \'1\') AS reviewed,questapproved,ss.supplier_no AS supplier_no
FROM suppliers c
INNER JOIN supplier_site ss ON c.supplier_id = ss.supplier_id
WHERE c.supplier_id != \'0\' AND ss.site_id = \'2\'
GROUP BY c.supplier_id
ORDER BY c.supplier_name ASC
LIMIT 0,20
Explain查询的结果如下
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ss ref site_id,supplier_id site_id 4 const 1287 Using where; Using temporary; Using filesort
1 PRIMARY c eq_ref PRIMARY PRIMARY 4 ss.supplier_id 1
3 DEPENDENT SUBQUERY q2 ref supplier_id,reviewed reviewed 4 const 263 Using where
2 DEPENDENT SUBQUERY q1 ref supplier_id,incomplete incomplete 4 const 254 Using where
计数查询存在的原因是因为我需要知道那些表中的行数,这不能在另一个查询中完成,因为结果还需要按这些值进行排序:(
解决方法
作为暗中的一击,这运行得更快吗? (我没有mysql来验证语法,因此可以原谅任何细微的错误,但您可能会明白)
SELECT c.supplier_id,supplier_name,address1,address2,address3,address4,suppliertype,postcode,contact_name,questions,reviewed
IF (active=1,\'Yes\',IF (active=2,\'NCR Only\',\'Inactive\')) AS rated,questapproved,ss.supplier_no AS supplier_no
FROM suppliers c
INNER JOIN supplier_site ss ON c.supplier_id = ss.supplier_id
inner join
(SELECT supplier_id,sum(if(incomplete=\'0\',1,0)) as questions,sum(if(incomplete=\'1\',0)) as reviewed FROM supplier_questions q1 group by supplier_id) as tmp
on c.supplier_id = tmp.supplier_id
WHERE c.supplier_id != \'0\' AND ss.site_id = \'2\'
GROUP BY c.supplier_id
ORDER BY c.supplier_name ASC LIMIT 0,20
,FROM suppliers c
INNER JOIN supplier_site ss ON c.supplier_id = ss.supplier_id
WHERE c.supplier_id != \'0\' AND ss.site_id = \'2\'
GROUP BY c.supplier_id
ORDER BY c.supplier_name ASC
由于自动生成的主键永远不会等于0(除非出现大的数据库设计错误),所以可以删除c.supplier_id!= \'0 \'子句。
ss.site_id = \'2 \'应该处于JOIN条件以提高可读性。
看起来这应该只与每个供应商的表Supplier_site中的一行匹配(如果这是您通常的1-N物-地址关系,即您正在选择每个供应商的第二个地址,则\'2 \'对应于\ '帐单地址\”之类的东西,因此GROUP BY c.supplier_id是无用的。如果GROUP BY实际执行了某项操作,则该查询是错误的,因为“ address \”列(可能来自于vendor_site表)将来自随机行。
所以这是简化的FROM(WHERE不在了):
FROM suppliers c
INNER JOIN supplier_site ss ON
(c.supplier_id = ss.supplier_id AND ss.site_id = \'2\')
ORDER BY c.supplier_name ASC
我想您在c.supplier_name上有一个索引,因此查询的这一部分应该非常快。
现在尝试以下查询:
SELECT a.*,ss.supplier_no AS supplier_no,IF (active=1,sum( q.incomplete = \'0\') AS questions,sum( q.reviewed = \'1\' ) AS reviewed
FROM
(
SELECT c.supplier_id,contact_name
FROM suppliers c
INNER JOIN supplier_site ss ON
(c.supplier_id = ss.supplier_id AND ss.site_id = \'2\')
ORDER BY c.supplier_name ASC
LIMIT 0,20
) a
LEFT JOIN supplier_questions q ON (q.supplier_id = c.supplier_id)
GROUP BY c.supplier_id
ORDER BY c.supplier_name;
,如果删除子选择,则结果如下:
SELECT c.supplier_id,COUNT(IF (q1.incomplete = \'0\',\'0\',null)) AS questions,COUNT(IF (q1.reviewed = \'1\',\'1\',null)) AS reviewed,ss.supplier_no AS supplier_no
FROM suppliers c
INNER JOIN supplier_site ss ON c.supplier_id = ss.supplier_id
LEFT OUTER JOIN supplier_questions q1 ON c.supplier_id = q1.supplier_id
WHERE c.supplier_id != \'0\' AND ss.site_id = \'2\'
GROUP BY c.supplier_id
ORDER BY c.supplier_name ASC
LIMIT 0,20
我没有可用的MySQL数据库,因此SQL可能有错误。
这个想法是删除子查询并用外部联接替换它们
并使用IF仅计算相关行。
,我将首先尝试通过按供应商预先查询汇总的问题计数并审查一次ONCE来进行重组。然后,加入其余的细节。通过使用STRAIGHT_JOIN关键字,它应该按照显示的顺序进行处理。这将首先进行预汇总,并以THAT为基础加入供应商,然后再加入供应商地点。不需要外部组,因为它无论如何都是基于供应商ID的。但是,如果连接到vendor_sites(您的ss.supplier_no),则意味着供应商具有多个位置。这是否意味着地址和活动状态列源自该表?
问题的加入是否应与特定的供应商及其对应的站点位置相关联?
此外,由于预查询在Supplier_id!= \'0 \'上具有WHERE子句,因此不需要下游,因为这将成为正常连接其他表的基础,从而将它们从结果集中删除。
SELECT STRAIGHT_JOIN
PreAggregate.supplier_id,PreAggregate.supplier_name,PreAggregate.Questions,PreAggregate.Reviewed,ss.supplier_no AS supplier_no
FROM
(select
s1.Supplier_ID,s1.Supplier_Name,SUM( IF( q1.Incomplete = \'0\',0 )) Questions,SUM( IF( q1.Reviewed = \'1\',0 )) Reviewed
from
suppliers s1
join supplier_questions q1
ON s1.supplier_id = q1.supplier_id
where
s1.supplier_id != \'0\'
group by
s1.Supplier_ID
ORDER BY
s1.supplier_name ASC ) PreAggregate
JOIN suppliers c
ON PreAggregate.Supplier_ID = c.Supplier_ID
JOIN supplier_site ss
ON PreAggregate.Supplier_ID = ss.supplier_id
AND ss.Site_ID = \'2\'
LIMIT 0,20
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。