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

Tengo un problema con una consulta de MySQL DB. Básicamente, estoy descubriendo que si indico un campo varchar (50) particular tag.name, mis consultas tardan más (x10) que no indexar el campo. Estoy tratando de acelerar esta consulta, sin embargo, mis esfuerzos parecen ser contraproducentes.MySQL index ralentizar consulta

La línea culpable y el campo parece ser:

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

me he dado cuenta de que si consulta la tabla tag directamente sin unirse con los mismos criterios y con el campo de nombre de un índice, no tengo la problema ... En realidad, funciona más rápido de lo esperado.

ejemplo de consulta **

 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 

de explicar con índice **

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

de explicar sin índice **

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

TABLA CREAR

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

Solución Final Parece que MySQL es sólo ordenadas según los datos de forma incorrecta. Al final, resultó más rápido mirar la tabla de etiquetas como una sub consulta que devuelve los identificadores.

+2

¿Cuáles son los índices en las otras tablas? ¿Qué cardinalidad se informa para cada uno de los índices? ¿Los has analizado recientemente? – symcbean

+0

de acuerdo con sym, intente analizar si parece que la clasificación de archivos está estropeando – jcho360

+0

eche un vistazo a esta página: http://www.mysqlperformanceblog.com/2009/03/05/what-does-using-filesort-mean -en-mysql/ – jcho360

Respuesta

1

¿Qué tan grandes son sus mesas? Me di cuenta en la primera explicación que tiene un "Uso temporal; Uso de filesort", que es malo. Es probable que su consulta se descargue en un disco, lo que lo hace mucho más lento que en las consultas de memoria. También trate de evitar el uso de "seleccionar *" y en su lugar consultar los campos mínimos necesarios.

+0

Su ejemplo, pero gracias por la sugerencia. Sé que utilizar el tipo de archivo es un problema, pero no entiendo por qué está sucediendo. Cuando agrego el índice, se usa una clasificación de archivos. Suelta el índice y funciona bien. – Lee

+0

Acabo de encontrar este hilo: http://forums.mysql.com/read.php?115,73760,73760#msg- 73760 su sugerencia es hacer una tabla de búsqueda para su tag.name para que use enteros en sus tablas de datos separadas de los nombres en sí –

+0

Así fue como resolví el problema .. Fue más rápido hacer una única búsqueda en la tabla de etiquetas nombre como una sub consulta. : D .. Gracias por la información. – Lee

3

Parece que article_id es la clave principal de la tabla de artículos.

Dado que está agrupando por article_id, MySQL debe devolver los registros en orden por esa columna, para poder realizar el GROUP BY.

Puede ver que sin el índice, escanea todos los registros en la tabla de artículos, pero que están al menos en orden por article_id, por lo que no es necesario ordenarlos más tarde. La optimización LIMIT se puede aplicar aquí, ya que está en orden, puede detenerse luego de que tenga cinco filas.

En la consulta con el índice en tag.name, en lugar de explorar toda la tabla de artículos, utiliza el índice, pero en la tabla de etiquetas, y comienza allí. Lamentablemente, al hacer esto, los registros deben ordenarse posteriormente por article.article_id para completar la cláusula GROUP BY. La optimización LIMIT no se puede aplicar, ya que debe devolver todo el conjunto de resultados, y luego ordenarlo para obtener las primeras 5 filas.

En este caso, MySQL simplemente adivina erróneamente.

Sin la cláusula LIMIT, supongo que usar el índice es más rápido, que es quizás lo que MySQL estaba adivinando.