テーブルをグループ (group_id) に大まかに分割する列 group_id を持つ大きなテーブル (250M 行) があります。次のインデックスがあります。
mysql> show indexes from table\G;
*************************** 13. row ***************************
Table: table
Non_unique: 1
Key_name: myindex
Seq_in_index: 1
Column_name: group_id
Collation: A
Cardinality: 181819
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
*************************** 14. row ***************************
Table: table
Non_unique: 1
Key_name: myindex
Seq_in_index: 2
Column_name: id
Collation: A
Cardinality: 213456239
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
次のクエリを実行したい:
mysql> explain select * from `table` WHERE (`table`.`type_id` IN (11, 17, 12, 19) AND `table`.`group_id` = 310248) ORDER BY `table`.`id` ASC LIMIT 201\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: table
type: index
possible_keys: [SOME INDEX NAMES]
key: PRIMARY
key_len: 4
ref: NULL
rows: 257386914
Extra: Using where
1 row in set (0.00 sec)
WHERE ... IN () のインデックス作成に問題があるため、いくつかの行をスキャンする必要があることを理解しています。しかし、驚くべきことに、主キー インデックスを使用して、可能な限り多くの行をスキャンすることを選択しています。
以下は、明白に (そして明らかに) 優れているようです。
mysql> explain select * from `table` USE INDEX (myindex) WHERE (`table`.`type_id` IN (11, 17, 12, 19) AND `table`.`group_id` = 310248) ORDER BY `table`.`id` ASC LIMIT 201\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: table
type: ref
possible_keys: myindex
key: myindex
key_len: 5
ref: const
rows: 1883760
Extra: Using where
1 row in set (0.00 sec)
LIMIT (2000) に大きな値を使用したり、異なる group_id の値を使用したり、ORDER BY を削除したり、type_id フィルターを削除したりすると、すべてインデックスが使用されます。ANALYZE TABLE を実行しました。
行の見積もりが非常に高いことに注意してください。
mysql> select count(*) from table where group_id=310248 and type_id in (11, 17, 12, 19) ;
+----------+
| count(*) |
+----------+
| 583868 |
+----------+
1 row in set (0.61 sec)
mysql バージョン:
Ver 5.1.57-rel12.8-log for debian-linux-gnu on x86_64 ((Percona Server (GPL), 12.8, Revision 233))
なぜ mysql は、1883760 行ではなく 257386914 行をスキャンする計画を選択するのでしょうか? 順次読み取りを評価する可能性があることは理解していますが、2000 行ではなく 2000 行のインデックスを選択するのはなぜですか? 別のグループ ID でフィルタリングするのはなぜですか?
編集済み:インデックス (group_id、id、type_id) の作成も試みたので、インデックス スキャンのみを使用してすべての並べ替えを実行できますが、そのインデックスを選択することはできません。