Không. Nếu bảng của bạn có công cụ InnoDB và PRIMARY KEY
là (pet_id)
, thì xác định chỉ mục phụ là (person_id)
hoặc (person_id, pet_id)
không có sự khác biệt.
Chỉ mục bao gồm cả pet_id
cột cũng vì vậy các giá trị được sắp xếp như (person_id, pet_id)
trong cả hai trường hợp.
Một truy vấn giống như truy vấn bạn có:
SELECT pet_id FROM yourtable
WHERE person_id = 127
ORDER BY pet_id ;
sẽ chỉ cần truy cập vào chỉ mục để nhận các giá trị và thậm chí nhiều hơn, nó sẽ không cần thực hiện bất kỳ sắp xếp nào, vì các pet_id
giá trị đã được sắp xếp trong chỉ mục. Bạn có thể xác minh điều này bằng cách xem các kế hoạch thực hiện ( EXPLAIN
):
Đầu tiên, chúng tôi thử với bảng 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)
Lưu ý các tập tin!
Bây giờ, MyISAM với chỉ số tổng hợp:
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 đã biến mất , như mong đợi.
Bây giờ, hãy thử tương tự với công cụ 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)
Không có tập tin nào cả! Mặc dù chỉ mục không rõ ràng có pet_id
cột, các giá trị vẫn ở đó và được sắp xếp. Bạn có thể kiểm tra xem nếu bạn xác định chỉ mục với (person_id, pet_id)
, EXPLAIN
thì giống hệt nhau.
Hãy thực sự làm điều đó, với InnoDB và chỉ mục tổng hợp:
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)
Kế hoạch giống hệt với trường hợp trước.
Để chắc chắn 100%, tôi cũng chạy 2 trường hợp cuối cùng (công cụ InnoDB, với các chỉ mục đơn và tổng hợp) cho phép file_per_table
cài đặt và thêm một vài nghìn hàng trong bảng:
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
Trong cả hai trường hợp, kiểm tra kích thước tệp thực tế, mang lại kết quả giống hệt nhau :
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
không phải là duy nhất, các bản ghi được sắp xếp vật lý theo(person_id, pet_id)
hoặc CHỈperson_id
?"