3

MySQL を使用して SQL クエリのパフォーマンスを理解しようとしています。PK のインデックスのみでは、クエリは 10 分以上で完了できませんでした。where 句 (タイムスタンプ、ホスト名、パス、タイプ) で使用されるすべての列にインデックスを追加したところ、クエリは約 50 秒で完了するようになりました。

ですから、これを引き起こしているクエリが何であるかを理解したいと思います。私の仮定は、私の内部サブクエリが何らかの形で必要な比較数の爆発を引き起こしているということです。

関連する 2 つのテーブルがあります。

ストレージ(~5,000 行 / 4.6MB) およびマシン(12 行、<4k)

クエリは次のとおりです。

SELECT T.hostname, T.path, T.used_pct, 
      T.used_gb, T.avail_gb, T.timestamp, machines.type AS type
      FROM storage AS T
      JOIN machines ON T.hostname = machines.hostname
      WHERE timestamp = ( SELECT max(timestamp) FROM storage AS st
                            WHERE st.hostname = T.hostname AND
                                              st.path = T.path)
      AND (machines.type = 'nfs')
      ORDER BY used_pct DESC

クエリの EXPLAIN EXTENDED は、次を返します。

id       select_type        table     type       possible_keys        key          key_len    ref                            rows     filtered      Extra
1        PRIMARY            machines  ref        hostname,type        type         768        const                          1        100.00        Using where; Using temporary; Using filesort
1        PRIMARY            T         ref        fk_hostname          fk_hostname  768        monitoring.machines.hostname   4535     100.00        Using where
2        DEPENDENT SUBQUERY st        ref        fk_hostname,path     path         1002       monitoring.T.path              648      100.00        Using where

行 1 の「余分な」列に「ファイルソートの使用」と質問が含まれて いる ことに注意してください。メモリ内のソートを完了してください。」

パフォーマンスの低下を引き起こしているこのクエリの性質は何ですか?

MySQL がこのクエリに「filesort」を使用する必要があるのはなぜですか?

4

1 に答える 1

3

インデックスは作成されず、作成するとすぐに存在します。そのため、テーブルにインデックスを追加すると、挿入と更新が遅くなります。

クエリの結果全体がキャッシュに入れられるため、初回以降はクエリが高速に実行されます。キャッシュを使用せずにクエリの速度を確認するには、次のことができます

SELECT SQL_NO_CACHE T.hostname ...

MySQL はfilesort通常、ORDER BYタイムスタンプの最大値を決定するために、またはあなたの場合に使用します。考えられるすべての値を調べてどの値が最大かを記憶する代わりに、MySQL は値を降順でソートし、最初の値を選択します。

では、なぜクエリが遅いのでしょうか? 2つのことが目に飛び込んできました。

1) サブクエリ

  WHERE timestamp = ( SELECT max(timestamp) FROM storage AS st
                        WHERE st.hostname = T.hostname AND
                                          st.path = T.path)

(ホスト名、パス) ごとに評価されます。タイムスタンプのインデックスを試してみてください(ちなみに、キーワード/データ型のような名前の列はお勧めしません)。それだけで解決しない場合は、クエリを書き直してみてください。MySQL マニュアルには 2 つの優れた例があります: The Rows Holding the Group-wise Maximum of a Specific Column

2) これは小さな問題ですが、char/varchar フィールドに参加しているようです。数字/IDははるかに高速です。

于 2013-05-20T18:09:27.687 に答える