2009-05-14 17 views
24

Una de mis consultas en MySQL 5.0.45 está funcionando lento en el "envío de datos" fase. La consulta es una selección simple, devuelve aproximadamente 300 campos de ID de enteros como conjunto de resultados.MySql - Envío lenta fase de datos

 
mysql> SELECT source_id FROM directions WHERE (destination_id = 10); 
+-----------+ 
| source_id | 
+-----------+ 
|   2 | 
|   8 | 
... 
|  2563 | 
+-----------+ 
341 rows in set (2.13 sec) 

estoy seguro de por qué se tenga en cuenta "envío de datos" fase tan lento y qué se puede hacer para que sea rápido. Tenga en cuenta que estoy ejecutando esta consulta en el indicador de MySQL en el servidor, por lo que realmente no espero que pase tanto tiempo "enviando datos". ¿Alguna pista?

Si ayuda, tengo 3 campos de texto en esta tabla, pero dado que no están siendo seleccionados, que espero que no son motivo de esta lentitud.

Esta consulta se ejecuta miles de veces al día y realmente no puede permitirse el lujo de pasar 2 segundos en él cada vez.

resultado de perfiles:

 
mysql> show profile for query 4; 
+--------------------------------+----------+ 
| Status       | Duration | 
+--------------------------------+----------+ 
| (initialization)    | 0.000003 | 
| checking query cache for query | 0.000051 | 
| checking permissions   | 0.000007 | 
| Opening tables     | 0.000011 | 
| System lock     | 0.000005 | 
| Table lock      | 0.000023 | 
| init       | 0.00002 | 
| optimizing      | 0.00001 | 
| statistics      | 0.00006 | 
| preparing      | 0.000014 | 
| executing      | 0.000005 | 
| Sending data     | 2.127019 | 
| end       | 0.000015 | 
| query end      | 0.000004 | 
| storing result in query cache | 0.000039 | 
| freeing items     | 0.000011 | 
| closing tables     | 0.000007 | 
| logging slow query    | 0.000047 | 
+--------------------------------+----------+ 
18 rows in set (0.00 sec) 

ACTUALIZACIÓN: He tropezó con la siguiente URL que dice

 
Each time means the time elapsed between the previous event and the new event. So, the line: 
| Sending data | 0.00016800 | 
means that 0.00016800 seconds elapsed between "executing" and "Sending data". It is, it takes 0.00016800 seconds to execute the query. 

http://forums.mysql.com/read.php?24,241461,242012#msg-242012

Puede alguien validar?

+7

La declaración no es cierto en la página enlazada. Si hace un 'SHOW PROCESSLIST' mientras la consulta se está ejecutando, mostrará que la consulta está en el estado ** Enviando datos **. (No en el anterior). - Y por favor, nadie dice que la lista de procesos muestra el * siguiente * paso en la ejecución. :) – vbence

+0

@vbence: ¿Alguna vez has visto una consulta que nos lleva más de unos pocos a ejecutar? La teoría anterior tiene sentido. –

+0

@ user9111337 Oh sí. Las sentencias agregadas (GROUP BY) con WHERE caluse generalmente darán como resultado selecciones que no pueden ser resueltas usando un índice (EXPLAIN ... dirá "USING WHERE") - si la tabla es lo suficientemente grande, esto puede llevar varios minutos. - ¿Cómo se informa esto? Puedes verlo por ti mismo probando un 'SHOW PROCESSLIST'. – vbence

Respuesta

1

¿Tiene índices sobre esta mesa? Dijiste que devuelve unos 300. ¿Pero a cuántos necesita buscar para encontrar esos 300?

15

Un explicar de planta suele ser el mejor lugar para empezar cada vez que tenga una consulta lenta. Para obtener uno, ejecute

DESCRIBE SELECT source_id FROM directions WHERE (destination_id = 10); 

Esto le mostrará una tabla con los pasos necesarios para ejecutar su consulta. Si ve un valor grande en la columna 'filas' y NULO en la columna 'clave', eso indica que su consulta debe escanear una gran cantidad de filas para determinar cuáles devolver.

En ese caso, la adición de un índice en Destination_id debería acelerar drásticamente la consulta, en algún costo para insertar y eliminar de velocidad (ya que también tendrá el índice que actualizarse).

+10

Aunque estoy de acuerdo en que una consulta EXPLAIN/DESCRIBE es la forma de encontrar cómo solucionarlo, realmente no describiste para qué sirve la fase de "enviar datos". Ver http://dev.mysql.com/doc/refman/5.0/en/general-thread-states.html –

-2

Su consulta pasa 2.127019 a ejecutar la consulta. Probablemente esto se deba a que tiene una gran cantidad de datos y le falta un índice en la columna destination_id. Pruebe:

CREAR INDICE index_destination_id EN direcciones (ID_destino);

Luego su solicitud se ejecutará sin problemas.

+3

Esta declaración es FALSA ver mi comentario sobre la pregunta. – vbence

+0

Pero para mí, en un escenario diferente, de hecho, agregar un índice resolvió mi consulta lenta: a veces se olvida lo obvio. –

6

Probablemente se podría mirar a parte de hardware del servidor MySQL. Como Mysql doc dice:

El envío de datos

El hilo está leyendo y filas de procesamiento de una instrucción SELECT, y el envío de datos al cliente. Debido a que las operaciones que se producen durante este estado tienden a realizar grandes cantidades de acceso al disco (lecturas), a menudo es el estado de mayor duración durante la vigencia de una consulta determinada.

lo tanto, si el servidor dispone de disco lenta de E/S debido a la enorme archivo db/mesa u opción tableperfile InnoDB discapacitados/inicia el proceso de accidente fragmentación/mal configurado RAID/disco (esperar antes de la muerte de disco)/cualquier otro razón de la lentitud de E/S del disco: podría ser razón por la que aumentó dramáticamente el paso de "Envío de datos" ya que en este servidor de la etapa se recopilan todos los datos solicitados del disco y se los envía al cliente.

Por supuesto, debe intentar optimizar la selección para usar índices primero y asegúrese de que esto no sea un problema de programación, ya que esto afecta este tiempo de etapa en la mayoría de los casos.

0

tuve el mismo problema: Enviar datos era muy lento, pero tenía los índices correctos etc.

Después de mucho excavar alrededor, me encontré con que mi join estaba comparando dos campos que se indexan, pero tenían diferentes Colación: una era latin1_swedish_ci y la otra era uft8_general_ci.

Una vez que les han sido enviadas a utf8 la consulta fue significativamente más rápida (de 2,7 segundos a 0.002 segundos)