結果セットが大きくなる可能性がある特定のデータベースクエリでパフォーマンスの問題が発生しています。
問題のクエリ、私はWHERE句に3つのAND
sを持っています
条項の順序は重要ですか?
同様に、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
そうは思わない。クエリオプティマイザは十分に賢いはずです。
WHERE句を並べ替えてみると、それぞれの場合でEXPLAINSが同じことを示していることがわかります。
このクエリを最適化するために何ができるかについて:ASI_EVENT_TIMEにインデックスはありますか? (これは、クエリを使用して結果を並べ替えることもできるため、このクエリにとって最も重要です)。
他の2つのフィールド(ASI_SEISMO_IDおよびASI_ACTIVITY_ID)にインデックスはありますか?
テーブル構造を投稿していただければ助かります。
いいえ、関係ありません。
オプティマイザは、SQLを解析した直後に一連の単純な変換を実行します。これはその1つです。
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 )
を=
とほぼ同じように扱うことができます。安全にプレイするには、次の順序に従ってください(各部分はオプションです)。
=
。INs
。MySQL where最適化ドキュメント と言う:
可読性を犠牲にしながら、クエリを書き直して算術演算を高速化したくなるかもしれません。 MySQLは同様の最適化を自動的に行うため、多くの場合、この作業を回避し、クエリをより理解しやすく保守しやすい形式にすることができます。 MySQLによって実行される最適化の一部は次のとおりです。
...
a結合の各テーブルに対して、より簡単なWHEREが作成され、テーブルの高速WHERE評価が取得されます。できるだけ早く行をスキップします。
- 各テーブルインデックスが照会され、最適化インデックスが使用されない限りオプティマイザは使用する方がより効率的であると信じていますテーブルスキャン。かつて、最適なインデックスがテーブルの30%を超えるかどうかに基づいてスキャンが使用されていましたが、固定パーセンテージでは、インデックスとスキャンのどちらを使用するかの選択が決定されなくなりました。オプティマイザーはより複雑になり、その見積もりはテーブルサイズ、行数、I/Oブロックサイズなどの追加の要素に基づいています。
このように、クエリオプティマイザーがクエリで列を使用したHOW順序を省略することは合理的です(MySQLだけでなく、SQLも宣言型言語および私たちが望む方法ではなく、私たちが望むことをしなければなりません)。
ただし、クエリの複合キーの列に同じ並べ替えを使用することは大好きですが、たとえば、ORMまたはActiveRecordを使用する場合、yii2などの一部のフレームワークでは、関係基準のカスタマイズが「オン」状態ですが、アプリケーションのさまざまな部分にQueryBuilderの機能が必要です。