Así, nunca he entendido el explicar de MySQL. Entiendo que el producto bruto de los conceptos que usted debe tener al menos una entrada en la possible_keys columna para que el uso de un índice, y que las consultas sencillas son las mejores. Pero ¿cuál es la diferencia entre el ref y eq_ref? ¿Cuál es la mejor manera de optimizar las consultas.

Por ejemplo, esta es mi última consulta que estoy tratando de averiguar por qué se tarda una eternidad (generados a partir de django modelos) :

+----+-------------+---------------------+--------+-----------------------------------------------------------+---------------------------------+---------+--------------------------------------+------+---------------------------------+
| id | select_type | table               | type   | possible_keys                                             | key                             | key_len | ref                                  | rows | Extra                           |
+----+-------------+---------------------+--------+-----------------------------------------------------------+---------------------------------+---------+--------------------------------------+------+---------------------------------+
|  1 | SIMPLE      | T6                  | ref    | yourock_achiever_achievement_id,yourock_achiever_alias_id | yourock_achiever_alias_id       | 4       | const                                |  244 | Using temporary; Using filesort |
|  1 | SIMPLE      | T5                  | eq_ref | PRIMARY                                                   | PRIMARY                         | 4       | paul.T6.achievement_id               |    1 | Using index                     |
|  1 | SIMPLE      | T4                  | ref    | yourock_achiever_achievement_id,yourock_achiever_alias_id | yourock_achiever_achievement_id | 4       | paul.T6.achievement_id               |  298 |                                 |
|  1 | SIMPLE      | yourock_alias       | eq_ref | PRIMARY                                                   | PRIMARY                         | 4       | paul.T4.alias_id                     |    1 | Using index                     |
|  1 | SIMPLE      | yourock_achiever    | ref    | yourock_achiever_achievement_id,yourock_achiever_alias_id | yourock_achiever_alias_id       | 4       | paul.T4.alias_id                     |  152 |                                 |
|  1 | SIMPLE      | yourock_achievement | eq_ref | PRIMARY                                                   | PRIMARY                         | 4       | paul.yourock_achiever.achievement_id |    1 |                                 |
+----+-------------+---------------------+--------+-----------------------------------------------------------+---------------------------------+---------+--------------------------------------+------+---------------------------------+
6 rows in set (0.00 sec)

Yo tenía la esperanza de aprender lo suficiente acerca de mysql explicar que la consulta no sería necesario. Por desgracia, parece que usted no puede obtener suficiente información de explicar la instrucción y la necesidad de la cruda SQL. Consulta :

SELECT  `yourock_achievement`.`id`,
        `yourock_achievement`.`modified`,
        `yourock_achievement`.`created`,
        `yourock_achievement`.`string_id`,
        `yourock_achievement`.`owner_id`,
        `yourock_achievement`.`name`,
        `yourock_achievement`.`description`,
        `yourock_achievement`.`owner_points`,
        `yourock_achievement`.`url`,
        `yourock_achievement`.`remote_image`,
        `yourock_achievement`.`image`,
        `yourock_achievement`.`parent_achievement_id`,
        `yourock_achievement`.`slug`,
        `yourock_achievement`.`true_points`
FROM    `yourock_achievement`
INNER JOIN
        `yourock_achiever`
ON       `yourock_achievement`.`id` = `yourock_achiever`.`achievement_id`
INNER JOIN
        `yourock_alias`
ON      `yourock_achiever`.`alias_id` = `yourock_alias`.`id`
INNER JOIN
        `yourock_achiever` T4
ON      `yourock_alias`.`id` = T4.`alias_id`
INNER JOIN
        `yourock_achievement` T5
ON      T4.`achievement_id` = T5.`id`
INNER JOIN
        `yourock_achiever` T6
ON      T5.`id` = T6.`achievement_id`
WHERE
        T6.`alias_id` = 6
ORDER BY
        `yourock_achievement`.`modified` DESC
  • No se muy bien el punto, pero me gustaría recomendar este de rendimiento de mysql optimización y supervisión: jetprofiler.com
  • Podría usted por favor enviar la consulta a sí misma?
  • Consulta SQL publicado
  • Podría usted por favor, calcular COUNT(*) de filas que se devuelven, como en mi post?
  • He intentado correr que consulta por 10 minutos, sin resultado. Puedo contar las entradas en las diferentes tablas, si quieres.
  • Ok, se terminó en 12 minutos. 349285347 filas… sí, supongo que eso responde a la pregunta 🙁 No debe ser un grupo en algún lugar, ninguna idea de cómo django tiró.

InformationsquelleAutor Paul Tarjan | 2009-07-21

2 Comentarios

  1. 18

    Pablo:

    eq_ref

    Una fila de lectura de esta tabla para cada combinación de filas de las tablas anteriores. Distinto del sistema y const tipos, este es el mejor tipo de combinación. Se utiliza cuando todas las partes de un índice son utilizados por la combinación y el índice es una CLAVE PRINCIPAL o índice ÚNICO.

    eq_ref puede ser utilizado para las columnas indizadas que se comparan con el operador=. El valor de comparación puede ser una constante o una expresión que se utiliza columnas de las tablas que se leen antes de esta tabla. En los siguientes ejemplos, MySQL puede utilizar un eq_ref unirse al proceso de ref_table:

    SELECT * FROM ref_table,other_table
    WHERE ref_table.key_column=other_table.column;
    
    SELECT * FROM ref_table,other_table
    WHERE ref_table.key_column_part1=other_table.column
    AND ref_table.key_column_part2=1;

    ref

    Todas las filas con la coincidencia de los valores del índice son de lectura de esta tabla para cada combinación de filas de las tablas anteriores. ref se utiliza si la combinación se utiliza sólo una más a la izquierda prefijo de la clave o si la clave no es una CLAVE PRINCIPAL o índice ÚNICO (en otras palabras, si la combinación no puede seleccionar una sola fila basado en el valor de la clave). Si la clave que se utiliza coincide con sólo un par de filas, este es un buen tipo de combinación.

    ref puede ser utilizado para las columnas indizadas que se comparan con el = o <=> operador. En los siguientes ejemplos, MySQL puede utilizar un ref unirse al proceso de ref_table:

    SELECT * FROM ref_table WHERE key_column=expr;
    
    SELECT * FROM ref_table,other_table
    WHERE ref_table.key_column=other_table.column;
    
    SELECT * FROM ref_table,other_table
    WHERE ref_table.key_column_part1=other_table.column
    AND ref_table.key_column_part2=1;

    Estos son una copia literal de MySQL manual: http://dev.mysql.com/doc/refman/5.0/en/using-explain.html

    Si puede publicar su consulta que se está llevando a para siempre, me podrían ayudar a determinar lo que se ralentice. También, por favor, especifique cuál es su definición de para siempre es. También, si usted puede proporcionar su «SHOW CREATE TABLE xxx;» las declaraciones de estos cuadros, me podrían ayudar en la optimización de su consulta tanto como sea posible.

    Lo que salta a mí de inmediato como un posible punto de mejora es el «Uso temporal; el Uso de filesort;». Esto significa que una tabla temporal que se creó para satisfacer la consulta (no necesariamente una mala cosa), y que el GRUPO/ORDEN designado no puede ser recuperada a partir de un índice, lo que resulta en un filesort.

    • Por favor, no lo copie al pie de la letra el manual.
  2. 4

    Consulta parece a proceso (244 * 298 * 152) = 11,052,224 registros, que de acuerdo a Using temporary; Using filesort necesitan ser ordenados.

    Esto puede tomar mucho tiempo.

    Si publicas tu consulta aquí, que probablemente será capaz de optimizar de alguna manera.

    Actualización:

    Consulta, de hecho, hace una serie de bucles anidados y parece producir un montón de valores que necesitan ser ordenados a continuación.

    Podría usted por favor, ejecute la siguiente consulta:

    SELECT  COUNT(*)
    FROM    `yourock_achievement`
    INNER JOIN
            `yourock_achiever`
    ON       `yourock_achievement`.`id` = `yourock_achiever`.`achievement_id`
    INNER JOIN
            `yourock_alias`
    ON      `yourock_achiever`.`alias_id` = `yourock_alias`.`id`
    INNER JOIN
            `yourock_achiever` T4
    ON      `yourock_alias`.`id` = T4.`alias_id`
    INNER JOIN
            `yourock_achievement` T5
    ON      T4.`achievement_id` = T5.`id`
    INNER JOIN
            `yourock_achiever` T6
    ON      T5.`id` = T6.`achievement_id`
    WHERE
            T6.`alias_id` = 6
    • Esto no es del todo exacta. Esos números no significan que la consulta devuelve que muchos registros. De hecho, se indica que MySQL tiene que leer este número de filas para determinar lo que va a regresar.
    • ya vemos que no hay adicionales Using where aquí, va a ser seguro asumir que todos estos filas de hecho serán devueltos (espesially que carecen de otro tipo de información sobre la consulta).
    • Que no puede ser asumido. Un simple «LÍMITE de 1», entre otras cosas, refuta su suposición.
    • tienes razón, en ese sentido no necesariamente tienen que ser devueltos al cliente, pero que todavía tienen que ser devueltos al clasificador / distinctifier (que está allí de acuerdo a Using filesort).
    • Voy a mejor palabra es el de «proceso» para evitar la confusión.
    • Consulta SQL publicado. Su fea…

Dejar respuesta

Please enter your comment!
Please enter your name here