我已经做了一些测试来优化下面的查询,但是没有一个帮助。
我尝试过的是
IN
子句中的其他属性来更改查询逻辑我正在使用的索引;
radacct (`_accttime`);
radacct (`username`);
radacct (`acctstoptime`,`_accttime`);
完整查询;
(SELECT *
FROM `radacct`
WHERE (radacct._accttime > NOW() - INTERVAL 1.2 HOUR)
AND radacct.acctstoptime IN
(SELECT MAX(radacct.acctstoptime)
FROM `radacct`
GROUP BY radacct.username) )
UNION
(SELECT *
FROM `radacct`
WHERE (radacct._accttime >= DATE_SUB(NOW(), INTERVAL 2 MONTH)
AND radacct.acctstoptime IS NULL) )
当我自己执行上面的SELECT
条语句时,它们仅花费几毫秒的时间。
我对IN
子句有疑问。所以这是需要时间的查询
答案 0 :(得分:1)
如我所见,您的问题是您的IN
中的依赖子查询。显然,优化器不会得到子查询在技术上没有太大变化的信息。 (同样,查询可能不是最理想的)。本质上,子查询是针对每一行执行的(这很糟糕)。
现在,我们必须找出哪一部分触发它成为从属,因为它不是真的。我的第一个尝试是给它一个不同的别名:
IN (SELECT MAX(inner.acctstoptime) FROM radacct AS `inner` GROUP BY inner.username)
如果这还不足以使其独立,请使其成为完整的联接(INNER,这样将从结果中丢弃未联接的行[=非最大行]):
INNER JOIN (
SELECT MAX(inner.accstoptime) as maxstoptime, inner.username
FROM `radacct` AS `inner`
GROUP BY inner.username
) sub ON (sub.maxstoptime=radacct.acctstoptime)
希望能达到目的。
由于您的结果中包含最多acctstoptime
个用户行,因此在极少数情况下,如果有一行具有acctstoptime的行,则该行可能包含一个用户的多个行,而不是该用户的最大值,但与另一个用户的最大值匹配。在连接部分中,您可以在在线子句中添加另一个条件。在IN子查询中,您将删除显式组,并添加WHERE radacct.username=inner.username
。 (这确实会使它成为一个显式的依赖子查询,但是优化程序可能能够处理它)
更新:由于沟通不畅...
所产生的带有联接的完整查询:
(SELECT DISTINCT radacct.*
FROM radacct
INNER JOIN (
SELECT MAX(inner.accstoptime) as maxstoptime, inner.username
FROM `radacct` AS `inner`
GROUP BY inner.username
) sub ON (sub.maxstoptime=radacct.acctstoptime)
WHERE (_accttime > NOW() - INTERVAL 1.2 HOUR)
)
UNION
(SELECT *
FROM `radacct`
WHERE (_accttime >= DATE_SUB(NOW(),INTERVAL 2 MONTH)
AND acctstoptime IS NULL)
)
您仍然可以在ON
子句中添加用户名比较。
此查询的作用是,它删除“ IN”选择器并强制加入中间结果(对于每个用户名,最大acctstoptime)。然后,且仅当acctstoptime是某个用户(或该用户,如果您添加用户名比较)的最大值,则该联接会将正常行连接到中间结果行。如果没有最大acctstoptime,因此没有联接“伙伴”,它将从结果中丢弃(由INNER
引起,LEFT JOIN
有点不足),因此仅保留行最长acctstoptime(在联盟的第一部分)。