これは、主要な母集団(タプルカーディナリティ)に基づく5%ルールと私が呼んでいるものによるものです。
偏ったカーディナリティが存在するテーブルにインデックスを付ける場合、MySQLクエリオプティマイザは常に最も抵抗の少ないパスを選択します。
例:テーブルに性別の列がある場合、カーディナリティはMとFの2つです。
そのような性別の列にインデックスを付けるのは何ですか?本質的に2つの巨大なリンクリストを取得します。
性別列のあるテーブルに100万行をロードすると、50%Mと50%Fが得られる可能性があります。
キーコンボ(私が言ったようにキーの母集団)のカーディナリティがテーブルの総数の5%を超える場合、クエリの最適化中にインデックスは役に立たなくなります。
さて、あなたの例に関して、なぜ2つの異なるEXPLAINプランがありますか?私の推測では、タグチームとしてのMySQLクエリオプティマイザーとInnoDBです。
最初のCREATETABLEでは、テーブルとインデックスは小さいながらもほぼ同じサイズであるため、全表スキャンではなくインデックススキャンを実行することでインデックスを優先することにしました 。一意でないインデックスは、インデックスエントリで各行の内部主キー(RowID)を引き継ぐため、インデックスはテーブル自体とほぼ同じサイズになることに注意してください。
2番目のCREATETABLEでは、別の列userが導入されたため、クエリオプティマイザーにまったく異なるシナリオが表示されるようになりました。テーブルはインデックスよりも大きくなりました 。したがって、クエリオプティマイザは、使用可能なインデックスの使用方法の解釈をより厳密にしました。それは私が前に述べた5%のルールに行きました。そのルールは惨めに失敗し、クエリオプティマイザは全表スキャンを支持することを決定しました。