mysql連合インデックスの失効問題を記録する

1217 ワード

今日1本のsql文が特に遅いことを発見して、1.9秒走って、大体の文は以下の通りです
SELECT DISTINCT
	c.id
FROM
	table_name c
WHERE
	c.`status` != 1
AND c.total >= 2
AND c.start_time >= '2020-01-01 00:00:00'
AND c.start_time < '2020-08-01 00:00:00'
AND c.id IN (....       id
)

sqlalchemyはライブラリ間でクエリーできないため、数百個の数千個のidは別のライブラリのテーブルからクエリーされます.
このテーブルにはすでに個別のインデックスと連合インデックスがたくさんあります.
explainを使用すると、keyフィールドでは、このクエリはidという個別インデックスのみを使用し、別のstatus、total、start_には使用されていません.timeの連合インデックスですがpossible_keysには、連合インデックスが使われる可能性があるのでおかしいと表示され、ネット検索を開始し、ある説!=,<>このようなインデックスを行かないで、私はc.`status`!=1 c.`status`in(2,3,4,5)に変更しましたが、結果的に後ろのインデックスには行かず、idの個別インデックスを使いました
どうしてかな
以前は、クエリーのフィールド順序が連合インデックスのフィールド順序と一致すると思っていたが、結果は役に立たなかった.
そしてstatus条件以降のすべての判断条件をコメントし、c.`status`=2のみで試してみると、やはりダメなのか、c.`status`=3のみに変更し、statusを使用した個別インデックスを発見
その後、c.`status`=2という条件データ量が大きすぎて、データベースがインデックスを使用するコストが大きすぎて、全テーブルスキャンを使用していると感じたのも、c.`status`=2の場合インデックスを使用していない理由であるため、連合インデックスを作成する際には、最も多くのデータを除外する条件フィールドを最初に置く必要があり、上記のsqlを例にとると、連合インデックスをstart_として作成するtime,status,totalのような順序で、時間条件が最初に最も多くのデータをフィルタリングしたと判断したので、statusがフィルタリングしたデータがtotalよりも優れていることを確認しました.
このような連合インデックスが作成されると、上記のsql文は0.14秒で実行されません.