2012-06-07 14 views
7
MySQL Server version: 5.0.95 
Tables All: InnoDB 

Mam problem z zapytaniem db MySQL. Zasadniczo stwierdzam, że jeśli indeksowanie konkretnego pola varchar (50) tag.name, moje zapytania trwają dłużej (x10) niż nie indeksowanie pola. Próbuję przyspieszyć tę kwerendę, jednak moje wysiłki wydają się być nieproduktywne.Indeks spowolnienia indeksowania MySQL

Linia sprawcy i pola wydaje się być:

WHERE `t`.`name` IN ('news','home') 

Zauważyłem, że jeśli kwerendy tabeli tag bezpośrednio bez sprzężenia przy użyciu tych samych kryteriów iz polu Nazwa indeksowanego, ja nie mam problem .. Działa to szybciej zgodnie z oczekiwaniami.

Przykład zapytania **

 SELECT `a`.*, `u`.`pen_name` 
     FROM `tag_link` `tl` 
    INNER JOIN `tag` `t` 
      ON `t`.`tag_id` = `tl`.`tag_id` 
    INNER JOIN `article` `a` 
      ON `a`.`article_id` = `tl`.`link_id` 
    INNER JOIN `user` `u` 
      ON `a`.`user_id` = `u`.`user_id` 
     WHERE `t`.`name` IN ('news','home') 
     AND `tl`.`type` = 'article' 
     AND `a`.`featured` = 'featured' 
    GROUP BY `article_id` 
     LIMIT 0 , 5 

wytłumaczyć wskaźnika **

| id | select_type | table | type | possible_keys   | key  | key_len | ref    | rows | Extra              | 
+----+-------------+-------+--------+--------------------------+---------+---------+-------------------+------+-----------------------------------------------------------+ 
| 1 | SIMPLE  | t  | range | PRIMARY,name    | name | 152  | NULL    | 4 | Using where; Using index; Using temporary; Using filesort | 
| 1 | SIMPLE  | tl | ref | tag_id,link_id,link_id_2 | tag_id | 4  | portal.t.tag_id | 10 | Using where            | 
| 1 | SIMPLE  | a  | eq_ref | PRIMARY,fk_article_user1 | PRIMARY | 4  | portal.tl.link_id | 1 | Using where            | 
| 1 | SIMPLE  | u  | eq_ref | PRIMARY     | PRIMARY | 4  | portal.a.user_id | 1 |               | 
+----+-------------+-------+--------+--------------------------+---------+---------+-------------------+------+-----------------------------------------------------------+ 

wyjaśniania bez wskaźnika **

+----+-------------+-------+--------+--------------------------+---------+---------+---------------------+------+-------------+ 
| id | select_type | table | type | possible_keys   | key  | key_len | ref     | rows | Extra  | 
+----+-------------+-------+--------+--------------------------+---------+---------+---------------------+------+-------------+ 
| 1 | SIMPLE  | a  | index | PRIMARY,fk_article_user1 | PRIMARY | 4  | NULL    | 8742 | Using where | 
| 1 | SIMPLE  | u  | eq_ref | PRIMARY     | PRIMARY | 4  | portal.a.user_id | 1 |    | 
| 1 | SIMPLE  | tl | ref | tag_id,link_id,link_id_2 | link_id | 4  | portal.a.article_id | 3 | Using where | 
| 1 | SIMPLE  | t  | eq_ref | PRIMARY     | PRIMARY | 4  | portal.tl.tag_id | 1 | Using where | 
+----+-------------+-------+--------+--------------------------+---------+---------+---------------------+------+-------------+ 

TABELA TWORZENIE

CREATE TABLE `tag` (
    `tag_id` int(11) NOT NULL auto_increment, 
    `name` varchar(50) NOT NULL, 
    `type` enum('layout','image') NOT NULL, 
    `create_dttm` datetime default NULL, 
    PRIMARY KEY (`tag_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=43077 DEFAULT CHARSET=utf8 

Indexs

SHOW INDEX FROM tag_link; 
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| tag_link |   0 | PRIMARY |   1 | tag_link_id | A   |  42023 |  NULL | NULL |  | BTREE  |   | 
| tag_link |   1 | tag_id |   1 | tag_id  | A   |  10505 |  NULL | NULL |  | BTREE  |   | 
| tag_link |   1 | link_id |   1 | link_id  | A   |  14007 |  NULL | NULL |  | BTREE  |   | 
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 

SHOW INDEX FROM article; 
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| article |   0 | PRIMARY   |   1 | article_id | A   |  5723 |  NULL | NULL |  | BTREE  |   | 
| article |   1 | fk_article_user1 |   1 | user_id  | A   |   1 |  NULL | NULL |  | BTREE  |   | 
| article |   1 | create_dttm  |   1 | create_dttm | A   |  5723 |  NULL | NULL | YES | BTREE  |   | 
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 

ostateczne rozwiązanie Wydaje się, że MySQL jest tylko sortowane dane nieprawidłowo. Ostatecznie okazało się, że szybciej przyjrzeć się tabeli znaczników jako subdomen zwracającej identyfikatory.

+2

Jakie są indeksy w innych tabelach? Jaka liczność jest zgłaszana dla każdego z indeksów? Czy analizowałeś je ostatnio? – symcbean

+0

Zgadzam się z sym, spróbuj yo zwróć uwagę, że plik się psuje – jcho360

+0

proszę spojrzeć na tę stronę: http://www.mysqlperformanceblog.com/2009/03/05/what-does-using-filesort-mean -in-mysql/ – jcho360

Odpowiedz

1

Jak duże są Twoje stoły? Zauważyłem w pierwszym wyjaśnieniu, że masz "Korzystanie z tymczasowego, Korzystanie z filesort", który jest zły. Twoje zapytanie prawdopodobnie zostanie zrzucone na dysk, co sprawia, że ​​jest wolniejszy niż w przypadku zapytań dotyczących pamięci. Staraj się również unikać "wybierz *" i zamiast tego wyszukuj wymagane minimalne pola.

+0

Jest to mój przykład, ale dzięki za napiwek. Wiem, że używanie sortowania plików jest problemem, ale nie rozumiem, dlaczego tak się dzieje. Kiedy dodaję indeks, używany jest fileort .. Upuść indeks i działa dobrze .. – Lee

+0

Właśnie natknąłem się na ten wątek: http://forums.mysql.com/read.php?115,73760,73760#msg- 73760 ich sugestia polega na utworzeniu tablicy odnośników dla twojego znacznika .name, więc użyjesz liczb całkowitych w twoich tabelach danych oddzielnych od samych nazw –

+0

W ten sposób rozwiązałem problem .. Szybciej było wykonać pojedyncze wyszukiwanie w tabeli znaczników przez nazwa jako pod-zapytanie. : D .. Dzięki za informację. – Lee

3

Wydaje się, że artykuł id jest kluczem podstawowym dla tabeli artykułów.

Ponieważ grupujesz według article_id, MySQL musi zwracać rekordy w kolejności według tej kolumny, aby wykonać GROUP BY.

Można zobaczyć, że bez indeksu skanuje wszystkie rekordy w tabeli artykułów, ale są one co najmniej w kolejności według artykułu id, więc nie jest wymagane późniejsze sortowanie. Optymalizację LIMIT można zastosować tutaj, ponieważ jest już w porządku, może się zatrzymać po otrzymaniu pięciu wierszy.

W zapytaniu z indeksem na tag.name, zamiast skanowania całej tabeli artykułów, wykorzystuje indeks, ale w stosunku do tabeli znaczników i zaczyna się tam. Niestety, podczas tej operacji, rekordy muszą być później posortowane według article.article_id, aby wypełnić klauzulę GROUP BY. Nie można zastosować optymalizacji LIMIT, ponieważ musi ona zwrócić cały zestaw wyników, a następnie go zamówić, aby uzyskać pierwsze 5 wierszy.

W tym przypadku MySQL po prostu zgadywa.

Bez klauzuli LIMIT, przypuszczam, że używanie indeksu jest szybsze, co jest prawdopodobnie tym, co MySQL zgadł.

Powiązane problemy