0

使用左连接的非常慢的 mysql 查询存在问题。

SELECT ip,T1.ipaddr,host,referrer,agent,page,url,thedate,DV,PV,notes
FROM visits_temp AS T1
LEFT JOIN (
    SELECT ipaddr,COUNT(DISTINCT LEFT(thedate,10)) AS DV
    FROM visits GROUP BY ipaddr
) AS T2 ON T1.ipaddr = T2.ipaddr
LEFT JOIN (
    SELECT ipaddr,notes
    FROM topvisitors
) As T3 ON T3.ipaddr = T1.ipaddr
LEFT JOIN (
    SELECT ipaddr,COUNT(ip) AS PV
    FROM visits
    GROUP BY ipaddr
) AS T4 ON T4.ipaddr = T1.ipaddr
WHERE referrer = '' AND
    thedate BETWEEN '2013-01-07 00:00:00' AND '2013-01-09 23:59:59'
GROUP BY T1.ip
ORDER BY thedate desc

此处的目标是获取网站的所有直接访问者流量,而不是 LEFT JOINS 进行查找以提供访问的总天数 (DV) 和查看的总页面数 (PV)。访问表目前有大约 290 万条记录,并且 ipaddr 和 date 字段已被索引。此查询需要近 90 秒才能完成。

SELECT ipaddr,COUNT(DISTINCT LEFT(thedate,10)) AS DV FROM visits GROUP BY ipaddr

或者

SELECT ipaddr,COUNT(ip) AS PV FROM visits GROUP BY ipaddr

LEFT JOINS 中的各个 select 语句在自行运行时将在 0.03 秒内完成。在这种情况下,也许 LEFT JOIN 不是正确的方法,我愿意接受替代方案。

4

2 回答 2

0

这 4 个子查询可能会减慢速度。

这应该与您的查询相同,只是更快:

SELECT ip,T1.ipaddr,host,referrer,agent,page,url,thedate,DV,PV,notes
FROM visits_temp AS T1
LEFT JOIN (
    SELECT ipaddr, COUNT(DISTINCT LEFT(thedate,10)) AS DV, COUNT(ip) AS PV
    FROM visits
    GROUP BY ipaddr
) AS T2 ON T1.ipaddr = T2.ipaddr
LEFT JOIN topvisitors T3 ON T3.ipaddr = T1.ipaddr
WHERE referrer = '' AND
    thedate BETWEEN '2013-01-07 00:00:00' AND '2013-01-09 23:59:59'
GROUP BY T1.ip
ORDER BY thedate desc

如果保证 的每一行在andT1中都有匹配的行,您可以将您的替换为,这应该允许优化器做更多的事情,这也可以加快速度(尽管有例外)。T2T3LEFT JOINJOIN

我无法想象这会返回所需的结果,它将在 上分组ipaddr,但随后只为每个返回(任何)这些分组中的 1 个ip。MySQL 不会阻止这一点。如果您详细说明您的要求(就您使用的字段/表格而言),解决这个问题应该不会太难(尽管这在技术上可能属于不同的问题)。

于 2013-01-11T10:29:43.817 回答
0

您在 where 子句中使用了 referrer 和 thedate。在visits_temp 表中的这两个字段上创建复合索引可能会提高性能。

确保在 topvisitors 表中的 ipaddr 字段上也有索引。

于 2013-01-09T16:45:46.873 回答