使用大量计数(行)和(行+行2)优化MySQL语句

时间:2010-03-22 03:45:55

标签: sql mysql optimization

我需要在一张桌子上使用InnoDB存储引擎,在任何给定时间内都有大约1mil左右的记录。它以非常快的速度插入记录,然后在几天内,也就是一周内删除。 ping表有大约一百万行,而网站表只有大约10,000行。

我的陈述是:

select url
from website ws, ping pi 
where ws.idproxy = pi.idproxy and pi.entrytime > curdate() - 3 and contentping+tcpping is not null 
group by url 
having sum(contentping+tcpping)/(count(*)-count(errortype)) < 500 and count(*) > 3 and 
count(errortype)/count(*) < .15
order by sum(contentping+tcpping)/(count(*)-count(errortype)) asc;

我在入场时添加了一个索引,但没有骰子。任何人都可以告诉我,我应该考虑什么来进行此查询的基本优化。结果集只有200行,所以我不会在那里被杀。

1 个答案:

答案 0 :(得分:2)

如果没有关系图式,我将不得不做出一些猜测。

  • 如果您正在制作WHERE a.attrname = b.attrname条款,则需要JOIN代替。

  • 使用COUNT(*)是多余的,有时效率低于COUNT(some_specific_attribute)。主键是一个很好的候选人。

  • 为什么要测试contentping+tcpping IS NOT NULL,要求进行不必要的计算,而不仅仅测试属性是否为空?

这是我改进的尝试:

SELECT url
FROM website AS ws
    JOIN ping AS pi
        ON ws.idproxy = pi.idproxy
WHERE
    pi.entrytime > CURDATE() - 3
    AND pi.contentping IS NOT NULL
    AND pi.tcpping IS NOT NULL
GROUP BY url
HAVING
    SUM(pi.contentping + pi.tcpping) / (COUNT(pi.idproxy) - COUNT(pi.errortype)) < 500
    AND COUNT(pi.idproxy) > 3
    AND COUNT(pi.errortype) / COUNT(pi.idproxy) < 0.15
ORDER BY
    SUM(pi.contentping + pi.tcpping) / (COUNT(pi.idproxy) - COUNT(pi.errortype)) ASC;

在HAVING和ORDER BY子句中执行大量相同的计算可能会降低您的成本。您可以将它们放在SELECT子句中,也可以创建一个将这些计算作为属性的视图,并使用该视图来访问值。