2

まず、この質問の「初心者」のような性質についてお詫び申し上げます。私はスタック交換で他の多くの遅いサブクエリの質問を見ました、しかし私は私の問題に修正を適用する方法がわかりませんでした。私は、単純な選択、挿入などを超えて、SQLにかなり慣れていません。

さまざまなデバイスについて、5分ごとに結果をMySQLテーブル(trends_uint)に記録するプリンター監視システムがあります。デバイスID(itemid)、タイムスタンプ(clock)、および印刷されたページ(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

どんな助けでもいただければ幸いです。前もって感謝します。

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

問題は、サブクエリのタイプが「DEPENDENTSUBQUERY」であるという事実です。これは、MySQLがプライマリクエリの一致する行ごとにそのサブクエリを1回実行していることを意味します。テーブルに200万行あるとすると、約200万回になります。

Group By演算子を使用するか、結合を使用して、サブクエリのロジックをプライマリクエリに移動してみてください。

于 2013-03-26T11:16:39.247 に答える
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

クエリは問題ありません。のインデックスが必要です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
                  )

このフォームを使用すると、インデックスがどのように使用されるかが明確になります(アイテムのインデックスに移動し、最後のクロック値を選択します)。

また、主キーとしてテーブルに自動インクリメントIDを含めることをお勧めします。これは、テーブル内の最新の行を取得しようとしているクエリを高速化するのに役立つ場合があります。

于 2013-03-26T14:02:08.060 に答える