5

6 つのレコードを含むテスト テーブル (table1) があります。複数の値の列 (col1) に基づいてデータを取得したいと考えていました。だから私は列にインデックスを付けました。強制インデックスを使用してすべての列 (*) を選択する IN 句で複数の値を渡すと、完全なテーブル スキャンではなく特定のレコードが取得されます。選択した列で同じクエリを実行すると、完全なテーブル スキャンが実行されることがわかります。

選択クエリで select all (*) を使用するのは良くないことを読みました。ただし、ここで select all (*) を使用しないと、テーブル全体のスキャンが行われます。mysql がクエリを読み取る方法を理解できません。この問題を解決するのを手伝ってください。

テーブル

+----+--------+---------+
| id | col1   | col2    |
+----+--------+---------+
|  1 | 100000 | E100000 |
|  2 | 100001 | E200001 |
|  3 | 100002 | E300002 |
|  4 | 100003 | E400003 |
|  5 | 100004 | E500004 |
|  6 | 100005 | E600005 |
+----+--------+---------+

索引

+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| table1   |          0 | PRIMARY  |            1 | id          | A         |           6 |     NULL | NULL   |      | BTREE      |         |               |
| table1   |          1 | col1     |            1 | col1        | A         |           6 |     NULL | NULL   |      | BTREE      |         |               |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

EXPLAIN (FORCE INDEX (col1) を使用し、すべての (*) 列を選択)

select * from table1 force index(col1) where col1 in ('100000', '100001');

+----+-------------+----------+-------+---------------+-------+---------+------+------+-------------+
| id | select_type | table    | type  | possible_keys | key   | key_len | ref  | rows | Extra       |
+----+-------------+----------+-------+---------------+-------+---------+------+------+-------------+
|  1 | SIMPLE      | table1   | range | col1          | col1  | 10      | NULL |    2 | Using where |
+----+-------------+----------+-------+---------------+-------+---------+------+------+-------------+

EXPLAIN (FORCE INDEX (col1) を使用し、すべてではなく 1 つの列データのみを選択 (*))

select col1 from table1 force index(col1) where col1 in ('100000', '100001');

+----+-------------+----------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table    | type  | possible_keys | key   | key_len | ref  | rows | Extra                    |
+----+-------------+----------+-------+---------------+-------+---------+------+------+--------------------------+
|  1 | SIMPLE      | table1   | range | col1          | col1  | 10      | NULL |    6 | Using where; Using index |
+----+-------------+----------+-------+---------------+-------+---------+------+------+--------------------------+
4

1 に答える 1

5
  1. MySQL オプティマイザーは、テーブルが小さすぎることを認識しており、最初にインデックスを検索して後でデータを取得するよりもフル スキャンの方が効率的です。
  2. 1 つの列のみを選択すると、MySQL オプティマイザーは、この列がインデックスにあることを認識し、テーブルからデータを取得する必要はありません。インデックスを読み取るだけで十分です。

オプティマイザーは、より効率的なものをどのように判断しますか? ディスク読み取りブロック操作の量を予測しようとします。

コメントで前に述べたように、大きなテーブルでは EXPLAIN は異なります。

于 2013-10-02T18:31:27.330 に答える