web-dev-qa-db-ja.com

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

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

問題のクエリ、私はWHERE句に3つのANDsを持っています

条項の順序は重要ですか?

同様に、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

41
Patrick

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

WHERE句を並べ替えてみると、それぞれの場合でEXPLAINSが同じことを示していることがわかります。


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

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

テーブル構造を投稿していただければ助かります。

26
ypercubeᵀᴹ

ドキュメント から:

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

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

したがって、はい、それは 複合インデックス の列の順序と同じである必要があります。

15
Gaius

いいえ、関係ありません。

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

10
Morgan Tocker

WHERE foo AND bar

と同じ最適化

WHEREバーとフー

しかしながら、

WHERE non-equal#1 AND AND non-equal#2

両方のパーツを最適化することはできません。例えば、

1と3の間で、かつb> 17の場合

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

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

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

結局のところ、INDEX(EVENT_TIME)はおそらく最も便利です。これは、ANDの1つに役立ち、ORDER BYの「ファイルソート」を回避するために使用される可能性があります。

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

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

pdate ...新しいバージョン(MySQL 5.7など)では、状況によってはIN( list of constants )=とほぼ同じように扱うことができます。安全にプレイするには、次の順序に従ってください(各部分はオプションです)。

  1. 任意の数の=
  2. 一部のINs
  3. 最大で1つの範囲。
8
Rick James

MySQL where最適化ドキュメント と言う:

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

  • ...

  • a結合の各テーブルに対して、より簡単なWHEREが作成され、テーブルの高速WHERE評価が取得されます。できるだけ早く行をスキップします

  • 各テーブルインデックスが照会され、最適化インデックスが使用されない限りオプティマイザは使用する方がより効率的であると信じていますテーブルスキャン。かつて、最適なインデックスがテーブルの30%を超えるかどうかに基づいてスキャンが使用されていましたが、固定パーセンテージでは、インデックスとスキャンのどちらを使用するかの選択が決定されなくなりました。オプティマイザーはより複雑になり、その見積もりはテーブルサイズ、行数、I/Oブロックサイズなどの追加の要素に基づいています。

このように、クエリオプティマイザーがクエリで列を使用したHOW順序を省略することは合理的です(MySQLだけでなく、SQLも宣言型言語および私たちが望む方法ではなく、私たちが望むことをしなければなりません)。

ただし、クエリの複合キーの列に同じ並べ替えを使用することは大好きですが、たとえば、ORMまたはActiveRecordを使用する場合、yii2などの一部のフレームワークでは、関係基準のカスタマイズが「オン」状態ですが、アプリケーションのさまざまな部分にQueryBuilderの機能が必要です。

1
Alix