2013-04-15 28 views
5

tôi có các bảng nhỏ, itemcategory:khác biệt mysql trong việc sử dụng chỉ số giữa MyISAM và InnoDB

CREATE TABLE `item` (
    `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(150) NOT NULL, 
    `category_id` mediumint(8) unsigned NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `name` (`name`), 
    KEY `category_id` (`category_id`) 
) CHARSET=utf8 

CREATE TABLE `category` (
    `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(150) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `name` (`name`) 
) CHARSET=utf8 

Tôi đã chèn 100 loại và 1000 mặt hàng.

Nếu tôi chạy này:

EXPLAIN SELECT item.id,category.name AS category_name FROM item JOIN category ON item.category_id=category.id; 

Sau đó, nếu động cơ của bảng là InnoDB tôi nhận được:

+----+-------------+----------+-------+---------------+-------------+---------+--------------------+------+-------------+ 
| id | select_type | table | type | possible_keys | key   | key_len | ref    | rows | Extra  | 
+----+-------------+----------+-------+---------------+-------------+---------+--------------------+------+-------------+ 
| 1 | SIMPLE  | category | index | PRIMARY  | name  | 452  | NULL    | 103 | Using index | 
| 1 | SIMPLE  | item  | ref | category_id | category_id | 3  | dbname.category.id | 5 | Using index | 
+----+-------------+----------+-------+---------------+-------------+---------+--------------------+------+-------------+ 

Trong khi đó, nếu tôi chuyển sang MyISAM (với alter table engine=myisam) tôi nhận được:

+----+-------------+----------+--------+---------------+---------+---------+-------------------------+------+-------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref      | rows | Extra | 
+----+-------------+----------+--------+---------------+---------+---------+-------------------------+------+-------+ 
| 1 | SIMPLE  | item  | ALL | category_id | NULL | NULL | NULL     | 1003 |  | 
| 1 | SIMPLE  | category | eq_ref | PRIMARY  | PRIMARY | 3  | dbname.item.category_id | 1 |  | 
+----+-------------+----------+--------+---------------+---------+---------+-------------------------+------+-------+ 

Câu hỏi của tôi là, tại sao sự khác biệt này trong cách chỉ mục được xử lý?

+1

bạn có chắc chắn bạn không phải xây dựng lại các chỉ số sau công cụ thay đổi không? – Sebas

+0

theo http://dev.mysql.com/doc/refman/5.0/en/rebuilding-tables.html, 'thay đổi công cụ bảng' là một cách để xây dựng lại nó. Tuy nhiên, tôi đã cố gắng bán phá giá và reimporting bảng, và kết quả là như nhau (đối với myisam) – periklis

Trả lời

4

Trong InnoDB, bất kỳ chỉ mục phụ nào trong nội bộ đều chứa cột khóa chính của bảng. Vì vậy, chỉ mục tên trên cột (tên) là hoàn toàn trên cột (tên, id).

Điều này có nghĩa là EXPLAIN hiển thị quyền truy cập của bạn vào bảng danh mục dưới dạng "quét chỉ mục" (điều này được hiển thị trong cột loại là "chỉ mục"). Bằng cách quét chỉ mục, nó cũng có quyền truy cập vào cột id, nó sử dụng để tra cứu các hàng trong bảng thứ hai, mục.

Sau đó, nó cũng tận dụng chỉ mục mục trên (category_id) thực sự là (category_id, id) và có thể tìm nạp item.id cho danh sách lựa chọn của bạn chỉ bằng cách đọc chỉ mục. Không cần đọc bảng (điều này được hiển thị trong cột Thêm là "Sử dụng chỉ mục").

MyISAM không lưu trữ khóa chính bằng khóa phụ theo cách này, do đó, nó không thể nhận được cùng một tối ưu hóa. Quyền truy cập vào bảng danh mục là loại "TẤT CẢ" có nghĩa là quét bảng.

Tôi hy vọng quyền truy cập vào mục bảng MyISAM sẽ là "ref" khi nó tra cứu các hàng bằng chỉ mục trên (category_id). Nhưng trình tối ưu hóa có thể nhận được kết quả sai lệch nếu bạn có rất ít hàng trong bảng hoặc nếu bạn chưa thực hiện ANALYZE TABLE item từ khi tạo chỉ mục.


Re cập nhật của bạn:

Dường như tôi ưu thích một chỉ số quét qua một bảng quét, vì vậy nó có cơ hội để làm một chỉ số quét trong InnoDB, và đặt các bảng category Đầu tiên. Trình tối ưu hóa quyết định sắp xếp lại các bảng thay vì sử dụng các bảng theo thứ tự bạn đã cung cấp cho chúng trong truy vấn của bạn.

Trong bảng MyISAM, sẽ có một bảng quét bất kỳ bảng nào mà nó chọn truy cập trước tiên, nhưng bằng cách đặt bảng danh mục thứ hai, nó tham gia vào chỉ mục chính PRIMARY của danh mục thay vì chỉ mục phụ của mục. Trình tối ưu hóa thích tra cứu đến khóa duy nhất hoặc chính (loại "eq_ref").

+0

Bạn là chính xác, các bảng có dữ liệu tối thiểu.Tôi đã phổ biến chúng với 100 danh mục và 1000 mục và đã cập nhật câu hỏi của tôi. Cảm ơn bạn đã trả lời của bạn, nó là enlightening – periklis

+0

@BillKarwin, Làm thế nào đến mysql không thể kết hợp các chỉ số của bảng 'item'? Có tất cả mọi thứ cần thiết: id và category_id, mặc dù id không được đưa vào chỉ mục KEY 'category_id' không giống như innodb – Sebas

+0

Thông thường MySQL chỉ sử dụng một chỉ mục cho mỗi tham chiếu bảng trong một truy vấn đã cho. Có những trường hợp khi nó có thể thực hiện thao tác hợp nhất chỉ mục, nhưng điều này xảy ra ít khi bạn nghĩ (xem http://dev.mysql.com/doc/refman/5.6/en/index-merge-optimization.html) –

Các vấn đề liên quan