MySQLでは、WHERE句の列の順序はクエリのパフォーマンスに影響しますか?


38

結果セットが大きくなる可能性がある特定のデータベースクエリでパフォーマンスの問題が発生しています。

問題のクエリAND、WHERE句に3つの

句の順序は重要ですか?

同様に、ASI_EVENT_TIME句を最初に配置すると(すべての句から結果のほとんどが削除されるため)。

それはクエリの実行時間を改善しますか?

クエリ:

SELECT DISTINCT  activity_seismo_info.* 
FROM `activity_seismo_info` 
WHERE 
    activity_seismo_info.ASI_ACTIVITY_ID IS NOT NULL  AND 
    activity_seismo_info.ASI_SEISMO_ID IN (43,44,...,259) AND 
    (
        activity_seismo_info.ASI_EVENT_TIME>='2011-03-10 00:00:00' AND 
        activity_seismo_info.ASI_EVENT_TIME<='2011-03-17 23:59:59'
    ) 

ORDER BY activity_seismo_info.ASI_EVENT_TIME DESC

クエリの説明:

+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
| id | select_type | table   | type  | possible_keys             | key          | key_len | ref  | rows  | Extra                       |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
|  1 | SIMPLE      | act...o | range | act...o_FI_1,act...o_FI_2 | act...o_FI_1 | 5       | NULL | 65412 | Using where; Using filesort |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+

を使用して:

PHP 5.2

MySQL 5.0.51a-3ubuntu5.4

Propel 1.3

Symfony 1.2.5


ORDER BYは、おそらく時間がかかるものです。「filesortの使用」は非常に遅い場合があります。アプリケーションロジックでの順序付けは、ORDER BYを使用するよりもずっと高速です。
マクレマ

この同じ質問をしばらく前(このサイトの前)にstackoverflowで尋ねました。そこに受け取った回答については、リンクを確認してください。stackoverflow.com/questions/3805863/...
スコット

2
@maclema-アプリケーションがデータベースよりもはるかに高速なマシンで実行されていない限り、アサーションは確かに間違っています。もちろん、アプリケーション内のすべてのソートロジックの無意味な負担は言うまでもありません。order byデータベースに属します。
ジャックダグラス

回答:


24

そうは思わない。クエリオプティマイザーは十分に賢いはずです。

WHERE句を並べ替えてみて、EXPLAINSが各ケースで同じことを示していることを確認してください。


このクエリを最適化するためにできることについて:ASI_EVENT_TIMEにインデックスはありますか?(これを使用して結果を並べ替えるので、これはこのクエリにとって最も重要だと思います)。

他の2つのフィールド(ASI_SEISMO_IDおよびASI_ACTIVITY_ID)にインデックスはありますか?

テーブル構造を投稿すると役立ちます。


イベント時間のインデックスを作成することを考えたことがありません。明日は開発データベースでそれを試して、顕著な違いがあるかどうかを確認します。
パトリック

@Patrickこのインデックスを使用する他のすべてのクエリがこの日付を降順で並べると仮定すると、インデックスキー(activity_seismo_info.ASI_EVENT_TIME)も降順で並べます。
マットM

@MattMインデックスキーを注文できることを知りませんでした。素晴らしいインデックスキーを注文すると、インデックスキーがないよりも悪いという点とは逆の方向のパフォーマンスの注文を必然的に損ないますか?
パトリック

@パトリックあなたは正しい。私の脳はSQL Serverの土地で立ち往生しています。MYSQLでソート順を指定でき、解析されますが、無視されます。すべてのインデックスは、MYSQLで昇順でソートされます。混乱させて申し訳ありません。
マットM

13

ドキュメントから:

テーブルに複数列のインデックスがある場合、オプティマイザーはインデックスの左端のプレフィックスを使用して行を検索できます。たとえば、(col1、col2、col3)に3列のインデックスがある場合、(col1)、(col1、col2)、および(col1、col2、col3)にインデックス検索機能があります。

列がインデックスの左端のプレフィックスを形成しない場合、MySQLはインデックスを使用できません。

そのため、複合インデックスの列の順序と同じにする必要があります。


4
テーブルに複数列のインデックスがある場合、左から列を選択することが重要ですが、選択する順序は重要ではありません。したがって、インデックスa、b、cがありWHERE c = 'foo' AND a = 'bar' AND b = 'foobar'、そのインデックスがまだ使用可能である場合。
16年

10

いいえ、それは問題ではありません。

オプティマイザーは、SQLを解析した直後に一連の単純な変換を行います-これはそのうちの1つです。


8

WHERE foo AND bar

と同じ最適化

WHEREバーとfoo

しかしながら、

等しくない#1と等しくない#2

両方の部分を最適化できません。例えば、

WHERE a BETWEEN 1 and 3 AND b> 17

INDEX(a、b)またはINDEX(b、a)をうまく利用できない

別の言い方をすると、WHERE句でANDで結合された「=」テストが最初に使用され、次に「=」以外の1つ(IN、BETWEEN、>など)を処理できます。効果的に最適化できるのは1つだけです。

クエリには、このような3つの句があります。

判明したように、INDEX(EVENT_TIME)はおそらく最も有用です。これはANDの1つに役立ち、ORDER BYの「filesort」を避けるために使用される可能性があります。

重複する行がない場合(なぜそうなるのでしょうか?)、DISTINCTを取り除きます。それはさらに多くの努力を引き起こします。

パフォーマンスの質問をするときは、SHOW CREATE TABLEとSHOW TABLE STATUSを提供してください。

更新... 新しいバージョン(例えば、MySQLの5.7)は、いくつかの状況では、御馳走IN( list of constants )ほぼ同様=。安全にプレイするには、この順序を守ってください(各部分はオプションです):

  1. 任意の数=
  2. いくつかINs
  3. 最大1つの範囲。

1

最適化のドキュメントに記載されているMySQL

読みやすさを犠牲にしながら、算術演算を高速化するためにクエリを書き直したくなるかもしれません。ので、MySQLが自動的に同様の最適化を行い、あなたは多くの場合、この作業を回避し、より理解しやすく、保守フォームでクエリを残すことができます。MySQLによって実行される最適化の一部は次のとおりです。

  • ...

  • 結合内の各テーブルに対して、よりシンプルなWHEREが構築され、テーブルの高速なWHERE評価を取得し、できるだけ早く行をスキップします

  • 各テーブルインデックスが照会され、オプティマイザがテーブルスキャンを使用する方が効率的である思わない限り、最適なインデックスが使用されます。かつては、最適なインデックスがテーブルの30%を超えているかどうかに基づいてスキャンが使用されていましたが、インデックスを使用するかスキャンを使用するかは固定の割合では決定されません。オプティマイザーはより複雑になり、テーブルサイズ、行数、I / Oブロックサイズなどの追加要因に基づいて推定が行われます。

このように、クエリオプティマイザーがクエリで列を使用したHOW順序を省略するのは合理的です(MySQLだけでなく、SQLは宣言型言語であり、必要な方法ではなく、必要な処理を行う必要があります)。

ただし、クエリの複合キーの列に同じ並べ替えが必要ですが、yii2などの一部のフレームワークでORMまたはActiveRecordを使用する場合など、避けられない場合があります。関係基準のカスタマイズは、 「オン」条件ですが、アプリケーションのさまざまな部分にQueryBuildersの機能が必要です。


-2

ANYあなたのWHERE / HAVING句で使用され、高い選択性があるさフィールド(一意の値の数/総レコード数> 10%〜20%)をしなければならないインデックスを作成します。

そのため、ASI_EVENT_TIME列に多くの可能な値がある場合、最初にそれらすべてにインデックスを付けます。その後、@ ypercubeが言ったように、それらを並べ替えて、EXPLAINが何を伝えているかを確認してください。すべて同じである必要があります。

さらに、インデックス作成SQL LIKEフィルタをご覧ください。答えが必要なものではありませんが、内部でインデックスがどのように機能するかについては引き続き学習します。

* 編集: インデックス作成の詳細については、コメントにある以下のリンクを参照してください。


8
-1すべての列にインデックスを付けることはベストプラクティスではありません。すべてのインデックスには複数の方法でコストがかかります。通常、選択性と使用頻度の順に、複数の列で構成される適切なインデックスを選択してください。これはSQL Serverの傾斜ですが、インデックス情報はまだ有効です:sqlskills.com/BLOGS/KIMBERLY/post/…
エリックハンフリー-lotsahelp

@Eric Humphrey +1説明とキンバリーのサイトへのリンク。
マットM

列にインデックスがあると、選択クエリmysqlperformanceblog.com/2007/08/28/…のパフォーマンスが低下することがあります。経験則は絶対に使用しないでください。時には機能することもあれば、機能しないこともあります。
スマー

そうですね。ただし、これは値の選択性が低い場合に有効です。Patrick(この質問の作成者)が使用するデータ型(DATETIME)を考慮すると、インデックス作成が推奨されます。通常、このタイプのフィールドには非常に大きな値のセットがありますが、いくつかの可能な日付のみを使用するという奇妙な状況がない限りです。*上記の回答を編集して、より明確で有効なステートメントを作成します。
アイ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.