データベースで次のクエリを実行しようとしています。
SELECT * FROM ts_cards WHERE ( cardstatus= 2 OR cardstatus= 3 ) AND ( cardtype= 1 OR cardtype= 2 ) ORDER BY cardserial DESC LIMIT 10;
3 つのフィールド (cardstatus、cardtype、cardserial) はすべてインデックス化されています。
mysql> SHOW INDEX FROM ts_cards;
+----------+------------+----------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------+------------+----------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+
| ts_cards | 0 | PRIMARY | 1 | card_id | A | 15000134 | NULL | NULL | | BTREE | |
| ts_cards | 1 | CardID | 1 | cardserial | A | 15000134 | NULL | NULL | | BTREE | |
| ts_cards | 1 | CardType | 1 | cardtype | A | 17 | NULL | NULL | | BTREE | |
| ts_cards | 1 | CardHolder | 1 | cardstatusholder | A | 17 | NULL | NULL | | BTREE | |
| ts_cards | 1 | CardExpiration | 1 | cardexpiredstatus | A | 17 | NULL | NULL | | BTREE | |
| ts_cards | 1 | CardStatus | 1 | cardstatus | A | 17 | NULL | NULL | | BTREE | |
+----------+------------+----------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+
6 rows in set (0.22 sec)
(はい、私はインデックスの名前が悪いことを知っています)
ただし、デフォルトでは、MySQL は cardstatus のインデックスのみを使用します。
mysql> EXPLAIN SELECT * FROM `ts_cards` WHERE ( cardstatus= 2 OR cardstatus= 3 ) AND ( cardtype= 1 OR cardtype= 2 ) ORDER BY cardserial DESC LIMIT 10;
+----+-------------+----------+-------+---------------------+------------+---------+------+---------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------------+------------+---------+------+---------+-----------------------------+
| 1 | SIMPLE | ts_cards | range | CardType,CardStatus | CardStatus | 1 | NULL | 3215967 | Using where; Using filesort |
+----+-------------+----------+-------+---------------------+------------+---------+------+---------+-----------------------------+
1 row in set (0.00 sec)
(cardserial のインデックスも考慮されていませんが、それは別の問題だと思います。)
「USE KEY」または「FORCE KEY」を使用すると、カードタイプのインデックスを使用できますが、カードタイプとカードステータスの両方を使用することはできません:
mysql> EXPLAIN SELECT * FROM `ts_cards` FORCE KEY (CardType) WHERE ( cardstatus= 2 OR cardstatus= 3 ) AND ( cardtype= 1 OR cardtype= 2 ) ORDER BY cardserial DESC LIMIT 10;
+----+-------------+----------+-------+---------------+----------+---------+------+---------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+----------+---------+------+---------+-----------------------------+
| 1 | SIMPLE | ts_cards | range | CardType | CardType | 1 | NULL | 6084861 | Using where; Using filesort |
+----+-------------+----------+-------+---------------+----------+---------+------+---------+-----------------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM `ts_cards` FORCE KEY (CardType,CardStatus) WHERE ( cardstatus= 2 OR cardstatus= 3 ) AND ( cardtype= 1 OR cardtype= 2 ) ORDER BY cardserial DESC LIMIT 10;
+----+-------------+----------+-------+---------------------+------------+---------+------+---------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------------+------------+---------+------+---------+-----------------------------+
| 1 | SIMPLE | ts_cards | range | CardType,CardStatus | CardStatus | 1 | NULL | 3215967 | Using where; Using filesort |
+----+-------------+----------+-------+---------------------+------------+---------+------+---------+-----------------------------+
1 row in set (0.00 sec)
MySQL に両方のインデックスを使用させてクエリを高速化するにはどうすればよいですか? cardtype インデックスと cardstatus インデックスはどちらも同じように定義されているようですが、cardstatus は cardtype よりも優先されるようです。