order by節なしで 'select * from lookup'を実行すると、Mysqlオプティマイザがセカンダリインデックスを選択するのはなぜですか?MySQL Query Optimizerは、クラスタ化されたプライマリインデックスに対してセカンダリインデックスを選択するのはなぜですか?
プライマリキーよりも重要なセカンダリインデックスを追加したことを前提としているため、これはちょっとばかりか、これはシーンの最適化の裏側です。
すべてのリーフノードのスキャンがこのクエリに答えるために必要なすべてのデータを提供できるため、主キーで結果を並べ替えることが期待されます。これはどこである(ランダムな非アルファベット順
insert into lookup values(1, "Zebra"),(2, "Aardvark"),(3, "Fish"),(4,"Dog"),(5,"Cat"),(6,"Mouse");
クエリでデータをいくつかのデータを挿入し
create table lookup (
id int not null,
primary key (id),
name varchar(25),
unique k_name (name)
) engine=innodb;
(AUTO_INCREMENTない注意してください)私は、単純なキー/値ペアのテーブルを作成し再現する
I)は、データが主キーの順序で返されることなど
mysql> select * from lookup;
+----+----------+
| id | name |
+----+----------+
| 2 | Aardvark |
| 5 | Cat |
| 4 | Dog |
| 3 | Fish |
| 6 | Mouse |
| 1 | Zebra |
+----+----------+
6 rows in set (0.00 sec)
どこに期待しますそうではありません - k_nameリーフノードのスキャンが完了したようです。ここに表示
mysql> explain select * from lookup;
+----+-------------+--------+-------+---------------+--------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------+--------+---------+------+------+-------------+
| 1 | SIMPLE | lookup | index | NULL | k_name | 28 | NULL | 6 | Using index |
+----+-------------+--------+-------+---------------+--------+---------+------+------+-------------+
1 row in set (0.00 sec)
私にはこれは、Mysqlがデータを返すためのカバレッジインデックスとしてk_nameを使用していると言います。 k_nameインデックスを削除すると、データはプライマリキーの順序で返されます。別の索引付けされていない列を追加すると、データは主キー順で返されます。
私の設定に関するいくつかの基本情報。
mysql> show table status like 'lookup'\G
*************************** 1. row ***************************
Name: lookup
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 6
Avg_row_length: 2730
Data_length: 16384
Max_data_length: 0
Index_length: 16384
Data_free: 0
Auto_increment: NULL
Create_time: 2011-11-15 10:42:35
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
mysql> select version();
+------------+
| version() |
+------------+
| 5.5.15-log |
+------------+
1 row in set (0.00 sec)
k_nameは2次インデックスです。候補キーの定義はインデックスとは関係ありません。定義上の主キーでさえ、インデックスとは関係ありません。それにもかかわらず、ほとんどのDBMSは主キーを定義するときに自動的にインデックスを作成します。 –
k_nameは二次索引ではありません。それはユニークキーであるため、PRIMARY KEYとまったく同じように動作します。一意のキーは、実際には、ユーザー定義のクラスタード・インデックスです。 PRIMARY KEYと同じくらいクラスタ化されたインデックスです。主キーが存在しない場合でも、ROWIDベースのgen_clust_indexが内部的に生成されます。このことの証明はInnoDBにあります。あなたは一日中、MyISAMに対してORDER BYの主キー列を実行できます。 InnoDBでは、UNIQUE KEYSを並べ替えることも、他のUNIQUE KEYSよりもPRIMARY KEYを優先してORDER-SELECT SELECTクエリを軽減することもできません。セカンダリインデックスは一意ではありません。 – RolandoMySQLDBA
クラスタ化インデックスは、PRIMARYキーのインデックスです。 MySQLは、プライマリキーがない場合は、UNIQUE以外のインデックスのみをクラスタ化インデックスとして使用します。さらに、k_nameのような2次索引だけにも、対応する行を参照するための主キー・データが含まれています。別の列を追加すると、k_nameはクラスタードードのようにすべてのデータを提供できないことがわかります。 http://dev.mysql.com/doc/innodb/1.1/en/glossary.html#glos_secondary_index k_nameは、主キーが削除されたときにクラスタ化インデックスになります。 –