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

У меня возникла проблема с запросом MySQL db. В основном я нахожу, что если я индексирую определенное поле varchar (50) tag.name, мои запросы занимают больше времени (x10), чем не индексируют поле. Я пытаюсь ускорить этот запрос, однако мои усилия, похоже, неэффективны.Запрос на замедление индекса MySQL MySQL

Виновник линии и поля, кажется:

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

Я заметил, что если я запросить tag таблицы непосредственно без объединения с использованием тех же критериев и поле имени индексируется, я не имею выпуск. Он работает быстрее, чем ожидалось.

Пример запрос **

 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 

РАЗЪЯСНЯЕТ с индексом **

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

РАЗЪЯСНЯЕТ без индекса **

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

TABLE CREATE

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 

индексирует

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

Окончательное решение кажется, что MySQL просто сортировал данные неправильно. В итоге оказалось, что быстрее искать таблицу тегов в качестве вспомогательного запроса, возвращающего идентификаторы.

+2

Каковы индексы на других таблицах? Какая мощность сообщается для каждого из индексов? Вы анализировали их недавно? – symcbean

+0

согласен с сим, попробуй летализировать, похоже, что файловый менеджер испортил – jcho360

+0

. Пожалуйста, загляните на эту страницу: http://www.mysqlperformanceblog.com/2009/03/05/what-does-using-filesort-mean -in-mysql/ – jcho360

ответ

1

Насколько велики ваши столы? Я заметил, что в первом объяснении у вас есть «Использование временного файла с файловым хранилищем», что плохо. Вероятно, ваш запрос сбрасывается на диск, что делает его медленнее, чем в запросах памяти. Также старайтесь избегать использования «select *» и вместо этого запрашивайте минимальные необходимые поля.

+0

Его пример, но спасибо за подсказку. Я знаю, что использование сортировки файлов является проблемой, но я не понимаю, почему это происходит. Когда я добавляю индекс, используется файловый порт .. Отбросьте индекс, и он отлично работает .. – Lee

+0

Я просто столкнулся с этой веткой: http://forums.mysql.com/read.php?115,73760,73760#msg- 73760 их предложение состоит в том, чтобы создать таблицу поиска для вашего tag.name, чтобы вы использовали целые числа в ваших таблицах данных, отдельно от самих имен –

+0

Так я решил проблему. Было быстрее сделать один поиск в таблице тегов на имя как дополнительный запрос. : D .. Спасибо за информацию. – Lee

3

Похоже, что article_id является основным ключом для таблицы статей.

Поскольку вы группируете article_id, MySQL должен возвращать записи по порядку этим столбцом, чтобы выполнить GROUP BY.

Вы можете видеть, что без индекса он сканирует все записи в таблице статей, но они по крайней мере в порядке со стороны article_id, поэтому последующий сортировка не требуется. Здесь может применяться оптимизация LIMIT, так как она уже в порядке, она может просто остановиться после того, как она получит пять строк.

В запросе с индексом на tag.name вместо сканирования всей таблицы статей используется индекс, но против таблицы тегов и начинается там. К сожалению, при этом записи впоследствии должны быть отсортированы с помощью article.article_id, чтобы завершить предложение GROUP BY. Оптимизация LIMIT не может применяться, поскольку она должна возвращать весь набор результатов, а затем заказывать его, чтобы получить первые 5 строк.

В этом случае MySQL просто ошибочно полагает.

Без предложения LIMIT, я предполагаю, что использование индекса происходит быстрее, что, возможно, является предположением MySQL.

Смежные вопросы