2

首先,我为这个问题的“新手”性质道歉。我在堆栈交换上看到了许多其他慢子查询问题,但我不确定如何将修复程序应用于我的问题。除了简单的选择、插入等之外,我对任何 SQL 都很陌生。

我有一个打印机监控系统,它每五分钟将其结果记录到 MySQL 表 (trends_uint) 中,用于一系列设备。它记录:设备 id (itemid)、时间戳 (clock) 和打印的页面 (value_avg)。从 PhpMyAdmin 我可以看到表索引是 itemid 和时钟的组合,我猜它们一起提供了一个独特的值。到目前为止,该表大约有 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

任何帮助,将不胜感激。提前致谢。

4

4 回答 4

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按此特定顺序)

于 2013-03-26T11:15:09.730 回答
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

于 2013-03-26T11:24:26.027 回答
0

问题在于子查询的类型为“DEPENDENT SUBQUERY”。这意味着 MySQL 为主查询的每个匹配行运行一次该子查询。如果您说该表有 200 万行,这意味着大约 200 万次。

尝试使用 Group By 运算符或使用连接将子查询的逻辑向上移动到主查询。

于 2013-03-26T11:16:39.247 回答
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
                  )

To ma,这种形式更清楚地说明了如何使用索引(进入项目的索引,选择最后一个时钟值)。

我还建议您在表中包含一个自动递增的 id 作为主键。这可以帮助您加快查询速度,以获取表中的最新行。

于 2013-03-26T14:02:08.060 回答