首先,我为这个问题的“新手”性质道歉。我在堆栈交换中看到了许多其他缓慢的子查询问题,但我不确定如何将修复应用于我的问题。除了简单的选择,插入等,我对任何SQL都不熟悉。
我有一个打印机监控系统,它可以每隔五分钟将结果记录到一个MySQL表(trends_uint)中,用于各种设备。它记录:设备ID(itemid),时间戳(时钟)和打印页面(value_avg)。从PhpMyAdmin我可以看到表索引是itemid和clock的组合,我猜它们一起提供了一个唯一的值。到目前为止,该表有大约200万行。
我的查询如下:
SELECT
tu1.itemid AS trends_uint_itemid,
tu1.clock AS time_value,
tu1.value_avg AS pages
FROM
trends_uint tu1
WHERE
(tu1.clock = (
SELECT max(tu2.clock)
FROM trends_uint tu2
WHERE tu1.itemid = tu2.itemid
)
)
ORDER BY tu1.clock DESC;
我尝试做的是为每个设备(itemid)选择最新的值(即最高时钟的value_avg),以便我可以绘制每个打印机打印的页数远。
我尝试为查询运行EXPLAIN,返回以下内容:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY tu1 ALL NULL NULL NULL NULL 1527815 Using where; Using filesort
2 DEPENDENT SUBQUERY tu2 ref PRIMARY PRIMARY 8 zabbix.tu1.itemid 115301 Using index
任何帮助将不胜感激。提前谢谢。
答案 0 :(得分:1)
这样的查询怎么样:
SELECT ...
FROM trends_uint t
INNER JOIN (
SELECT MAX(clock) AS clock, itemid
FROM trends_uint
GROUP BY itemid
) x ON x.itemid = t.itemid AND t.clock = x.clock
假设您的表中有一个复合索引:itemid + clock
(按此特定顺序)
答案 1 :(得分:0)
问题在于子查询的类型为“DEPENDENT SUBQUERY”。这意味着MySQL正在为主查询的每个匹配行运行该子查询一次。如果你说这个表有200万行意味着大约200万次。
尝试使用Group By运算符或使用连接将子查询的逻辑移动到主查询。
答案 2 :(得分:0)
如果使用显式子查询,它会有所不同吗?
SELECT
tu1.itemid AS trends_uint_itemid,
tu1.clock AS time_value,
tu1.value_avg AS pages
FROM
trends_uint tu1
JOIN
(
SELECT
itemid as theItem
,max(tu2.clock) AS LatestTime
FROM trends_uint tu2
GROUP BY itemid
) LatestClockForEachItem
ON tu1.itemid = LatestClockForEachItem.theItem
AND tu1.clock = LatestClockForEachItem.LatestTime
ORDER BY tu1.clock DESC;
PS。 SQL小提琴:http://sqlfiddle.com/#!2/bac3b/2
答案 3 :(得分:0)
您的查询没问题。您需要trends_uint(itemid, clock)
上的索引。
您还可以将子查询表示为:
tu1.clock = (
SELECT tu2.clock
FROM trends_uint tu2
WHERE tu1.itemid = tu2.itemid
order by tu2.clock desc
limit 1
)
对于ma来说,这个表单更清楚了如何使用索引(进入项目的索引,选择最后一个时钟值)。
我还建议您在表中包含一个自动递增ID作为主键。这可以帮助您加快查询,同时尝试获取表中最新的行。