2013-04-15 11 views
5

mam te małe stoliki, item i category:różnica mysql w użyciu indeksu MyISAM i InnoDB między

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 

mam wstawione 100 kategorie i 1000 elementów.

Jeśli uruchomię to:

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

Następnie, jeśli silnik tabelach jest InnoDB uzyskać:

+----+-------------+----------+-------+---------------+-------------+---------+--------------------+------+-------------+ 
| 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 | 
+----+-------------+----------+-------+---------------+-------------+---------+--------------------+------+-------------+ 

Natomiast jeśli przełączyć do MyISAM (z alter table engine=myisam) uzyskać:

+----+-------------+----------+--------+---------------+---------+---------+-------------------------+------+-------+ 
| 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 |  | 
+----+-------------+----------+--------+---------------+---------+---------+-------------------------+------+-------+ 

Moje pytanie brzmi, dlaczego ta różnica w sposobie obsługi indeksów?

+1

jesteś pewien, że nie musisz także odbudowywać indeksów po zmianie silnika? – Sebas

+0

zgodnie z http://dev.mysql.com/doc/refman/5.0/en/rebuilding-tables.html, 'alter table engine' jest sposobem na przebudowanie go. Niemniej jednak próbowałem wyrzucać i ponownie importować tabele, a wynik był taki sam (dla myisam). – periklis

Odpowiedz

4

W InnoDB każdy indeks drugorzędny zawiera wewnętrznie kolumnę klucza podstawowego tabeli. Tak więc indeks nazwa w kolumnie (nazwa) jest niejawnie w kolumnach (nazwa, identyfikator).

Oznacza to, że EXPLAIN pokazuje twój dostęp do tabeli kategorii jako "skan indeksu" (jest to pokazane w kolumnie typu jako "indeks"). Skanując indeks, ma również dostęp do kolumny identyfikatora, której używa do wyszukiwania wierszy w drugiej tabeli, pozycji.

Następnie korzysta z indeksu item (category_id), który jest naprawdę (id_categorii, id), i jest w stanie pobrać item.id do listy select po prostu czytając indeks. Nie trzeba w ogóle czytać tabeli (jest to pokazane w kolumnie Extra jako "Korzystanie z indeksu").

MyISAM nie przechowuje kluczy podstawowych za pomocą klucza dodatkowego w ten sposób, więc nie może uzyskać takich samych optymalizacji. Dostęp do tabeli kategorii jest typu "ALL", co oznacza skanowanie tabeli.

Spodziewam się, że dostęp do elementu tabeli MyISAM będzie "ref", ponieważ wyszukuje wiersze przy użyciu indeksu na (id_kategorii). Optymalizator może jednak uzyskać zniekształcone wyniki, jeśli w wierszu tabeli znajduje się bardzo mało wierszy lub jeśli nie został utworzony indeks ANALYZE TABLE item.


Re aktualizacją:

Wygląda optymalizator preferuje indeksu skanowanie nad stołem-scan, więc przy tej okazji zrobić indeksu skanowanie w InnoDB i umieszcza tabelę kategorii pierwszy. Optymalizator postanawia zmienić kolejność tabel, zamiast korzystać z tabel w kolejności podanej w zapytaniu.

W tabelach MyISAM zostanie przeprowadzony jeden przegląd tabeli, w zależności od tego, do której stołu będzie on miał pierwszeństwo, ale umieszczając tablicę kategorii na drugim miejscu, dołącza ona do indeksu klucza PRIMARY kategorii zamiast do indeksu wtórnego elementu. Optymalizator preferuje odnośniki do klucza unikalnego lub podstawowego (wpisz "eq_ref").

+0

Masz rację, tabele miały minimalne dane.Zapełniłem je 100 kategoriami i 1000 pozycji i zaktualizowałem moje pytanie. Dziękuję za odpowiedź, jest oświecająca – periklis

+0

@BillKarwin, Jak to możliwe, że mysql nie może łączyć indeksów tabeli "item"? Jest wszystko, czego potrzebuje: id i category_id, nawet jeśli id ​​nie jest zawarty w KEY 'category_id' index inaczej niż w innodb – Sebas

+0

Zwykle MySQL używa tylko jednego indeksu na odwołanie do tabeli w danym zapytaniu. Zdarzają się przypadki, w których można wykonać operację łączenia indeksów, ale występują one rzadziej, niż mogłoby się wydawać (patrz http://dev.mysql.com/doc/refman/5.6/en/index-merge-optimization.html) –

Powiązane problemy