いいえ。テーブルにInnoDBエンジンとPRIMARY KEY
isが含ま(pet_id)
れている(person_id)
場合、セカンダリインデックスをとして定義し(person_id, pet_id)
ても違いはありません。
インデックスにはpet_id
列も含まれるため(person_id, pet_id)
、両方の場合と同様に値がソートされます。
あなたが持っているようなクエリ:
SELECT pet_id FROM yourtable
WHERE person_id = 127
ORDER BY pet_id ;
値を取得するにはインデックスのみにアクセスする必要があります。さらに、pet_id
値はすでにインデックスで並べ替えられているため、並べ替えを行う必要はありません。これは、実行プラン(EXPLAIN
)を見て確認できます。
まず、MyISAMテーブルを試してみます。
CREATE TABLE table pets
( pet_id int not null auto_increment PRIMARY KEY,
person_id int not null,
INDEX person_ix (person_id)
) ENGINE = myisam ;
INSERT INTO pets (person_id)
VALUES (1),(2),(3),(1),(2),(3),(4),(1),(8),(1),(2),(3) ;
mysql> EXPLAIN SELECT pet_id FROM pets
WHERE person_id = 2
ORDER BY pet_id asc \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: pets
type: ref
possible_keys: person_ix
key: person_ix
key_len: 4
ref: const
rows: 3
Extra: Using where; Using filesort
1 row in set (0.00 sec)
filesortに注意してください!
さて、複合インデックスを持つMyISAM:
DROP TABLE IF EXISTS pets ;
CREATE TABLE table pets
( pet_id int not null auto_increment PRIMARY KEY,
person_id int not null,
INDEX person_ix (person_id, pet_id) -- composite index
) ENGINE = myisam ;
INSERT INTO pets (person_id)
VALUES (1),(2),(3),(1),(2),(3),(4),(1),(8),(1),(2),(3) ;
mysql> EXPLAIN SELECT pet_id FROM pets
WHERE person_id = 2
ORDER BY pet_id asc \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: pets
type: ref
possible_keys: person_ix
key: person_ix
key_len: 4
ref: const
rows: 3
Extra: Using where; Using index
1 row in set (0.00 sec)
予想通り、Filesortはなくなりました。
InnoDBエンジンで同じことを試してみましょう:
DROP TABLE IF EXISTS pets ;
CREATE TABLE table pets
( pet_id int not null auto_increment PRIMARY KEY,
person_id int not null,
INDEX person_ix (person_id) -- simple index
) ENGINE = innodb ; -- InnoDB engine
INSERT INTO pets (person_id)
VALUES (1),(2),(3),(1),(2),(3),(4),(1),(8),(1),(2),(3) ;
mysql> EXPLAIN SELECT pet_id FROM pets
WHERE person_id = 2
ORDER BY pet_id asc \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: pets
type: ref
possible_keys: person_ix
key: person_ix
key_len: 4
ref: const
rows: 3
Extra: Using where; Using index
1 row in set (0.00 sec)
filesortもありません!インデックスには明示的にpet_id
列がありませんが、値はそこにあり、並べ替えられています。でインデックスを定義すると(person_id, pet_id)
、EXPLAIN
が同じであることを確認できます。
InnoDBと複合インデックスを使用して、実際にそれを実行しましょう。
DROP TABLE IF EXISTS pets ;
CREATE TABLE table pets
( pet_id int not null auto_increment PRIMARY KEY,
person_id int not null,
INDEX person_ix (person_id, pet_id) -- composite index
) ENGINE = innodb ; -- InnoDB engine
INSERT INTO pets (person_id)
VALUES (1),(2),(3),(1),(2),(3),(4),(1),(8),(1),(2),(3) ;
mysql> EXPLAIN SELECT pet_id FROM pets
WHERE person_id = 2
ORDER BY pet_id asc \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: pets
type: ref
possible_keys: person_ix
key: person_ix
key_len: 4
ref: const
rows: 3
Extra: Using where; Using index
1 row in set (0.00 sec)
前のケースと同じ計画。
100%確実にするために、最後の2つのケース(InnoDBエンジン、単一インデックスと複合インデックス)も実行して、file_per_table
設定を有効にし、テーブルに数千行を追加します。
DROP TABLE IF EXISTS ... ;
CREATE TABLE ... ;
mysql> INSERT INTO pets (person_id)
VALUES (1),(2),(3),(1),(2),(3),(4),(1),(8),(1),(2),(3) ;
Query OK, 12 rows affected (0.00 sec)
Records: 12 Duplicates: 0 Warnings: 0
mysql> INSERT INTO pets (person_id)
VALUES (1),(2),(3),(1),(2),(3),(4),(1),(8),(1),(2),(3),(127) ;
Query OK, 13 rows affected (0.00 sec)
Records: 13 Duplicates: 0 Warnings: 0
mysql> INSERT INTO pets (person_id)
VALUES (1),(2),(3),(1),(2),(3),(4),(1),(8),(1),(2),(3),(127) ;
Query OK, 13 rows affected (0.00 sec)
Records: 13 Duplicates: 0 Warnings: 0
mysql> INSERT INTO pets (person_id)
SELECT a.person_id+b.person_id-1
FROM pets a CROSS JOIN pets b CROSS JOIN pets c ;
Query OK, 54872 rows affected (0.47 sec)
Records: 54872 Duplicates: 0 Warnings: 0
どちらの場合も、実際のファイルサイズを確認すると、同じ結果が得られます。
ypercube@apollo:~$ sudo ls -la /var/lib/mysql/x/ | grep pets
-rw-rw---- 1 mysql mysql 8604 Apr 21 07:25 pets.frm
-rw-rw---- 1 mysql mysql 11534336 Apr 21 07:25 pets.ibd
person_id
ユニークでないなら、レコードは物理的に、(person_id, pet_id)
またはちょうどによってソートされperson_id
ますか?」