2009-09-18 13 views
15

Tengo una tabla de tamaño modesto, 277k registros en este momento, en los que estoy tratando de hacer una búsqueda FULLTEXT. La búsqueda parece ser muy rápida hasta que llega a la fase de envío de datos.MySQL "Enviando datos" terriblemente lento

La Tabla:

CREATE TABLE `sqinquiries_inquiry` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `ts` datetime NOT NULL, 
    `names` longtext NOT NULL, 
    `emails` longtext NOT NULL, 
    PRIMARY KEY (`id`), 
    FULLTEXT KEY `sqinquiries_inquiry_search` (`names`,`emails`) 
) ENGINE=MyISAM AUTO_INCREMENT=305560 DEFAULT CHARSET=latin1 

la consulta:

SELECT * FROM `sqinquiries_inquiry` WHERE (
    MATCH (`sqinquiries_inquiry`.`names`) AGAINST ('smith' IN BOOLEAN MODE) OR 
    MATCH (`sqinquiries_inquiry`.`emails`) AGAINST ('smith' IN BOOLEAN MODE) 
) ORDER BY `sqinquiries_inquiry`.`id` DESC LIMIT 100 

El Perfil: (I cortó a cabo información aparentemente inútil)

+-------------------------+----------+ 
| Status     | Duration | 
+-------------------------+----------+ 
| preparing    | 0.000014 | 
| FULLTEXT initialization | 0.000015 | 
| executing    | 0.000004 | 
| Sorting result   | 0.000008 | 
| Sending data   | 2.247934 | 
| end      | 0.000011 | 
| query end    | 0.000003 | 
+-------------------------+----------+ 

La DESCRIBE se ve muy bien, un simple chiste: la descripción:

id: 1 
select_type: SIMPLE 
table: sqinquiries_inquiry 
type: index 
possible_keys: NULL 
key: PRIMARY 
key_len: 4 
ref: NULL 
rows: 100 
Extra: Using where 

Así que lo que no entiendo es donde el 2,25 segundos de envío de datos está viniendo? Veo un rendimiento similar en Python y en la consola mysql, ambos conectando a localhost.

actualizaciones:

  • Per comentario solicitando el tamaño medio de la fila, que es: 53.8485
  • por comentario, aquí es el DESCRIBE anteriormente.
+0

¿Cuán grande es la cantidad de datos que está recuperando? si no sabe, mire las estadísticas de la tabla y díganos el tamaño promedio de la fila. – longneck

+0

No estaba seguro de cómo averiguar el tamaño promedio de la fila, así que arrojé el resultado de esto hasta arriba: 'SELECCIONAR AVG (LONGITUD (nombres) + LONGITUD (correos electrónicos) + LONGITUD (id) + LONGITUD (ts)) como promedio_vg de sqinquiries_inquiry'. Si hay una mejor manera, por favor avíseme. –

+0

El problema es que su 'FULLTEXT KEY' no se usa. ¿Podría publicar el 'DESCRIBE'? – Quassnoi

Respuesta

32

El DESCRIBE se ve muy bien, un simple chiste.

Dado que solo está utilizando una tabla en su consulta, no puede ser otra que una línea.

Sin embargo, su consulta no utiliza el índice FULLTEXT.

Para que el índice sea utilizable, se debe reescribir la consulta un poco:

SELECT * 
FROM sqinquiries_inquiry 
WHERE MATCH (names, emails) AGAINST ('smith' IN BOOLEAN MODE) 
ORDER BY 
     id DESC 
LIMIT 100 

MATCH sólo se utiliza el índice si el partido contra el que el conjunto exacto de columnas del índice se define en.

Por lo tanto, su consulta utiliza el escaneo de índice en id: Using index; Using where al final de su DESCRIBE.

Sending data es bastante engañoso: esto es en realidad el tiempo transcurrido entre el final de la operación anterior y el final de la operación actual.

Por ejemplo, me acaba de ejecutar esta consulta:

SET profiling = 1; 

SELECT * 
FROM t_source 
WHERE id + 1 = 999999; 

SHOW PROFILE FOR QUERY 39; 

que volvió una sola fila y este perfil:

'starting', 0.000106 
'Opening tables', 0.000017 
'System lock', 0.000005 
'Table lock', 0.000014 
'init', 0.000033 
'optimizing', 0.000009 
'statistics', 0.000013 
'preparing', 0.000010 
'executing', 0.000003 
'Sending data', 0.126565 
'end', 0.000007 
'query end', 0.000004 
'freeing items', 0.000053 
'logging slow query', 0.000002 
'cleaning up', 0.000005 

Dado que el índice no es utilizable MySQL, necesita llevar a cabo la mesa llena escanear.

0.126565 segundos son el tiempo desde el inicio de la ejecución (el momento en que se leyó la primera fila) y el final en la ejecución (la hora en que se envió la última fila al cliente).

Esta última fila está al final de la tabla y tardó mucho tiempo en encontrarla y enviarla.

P. S. Editado para eliminar el downvote :)

+0

Estoy usando la versión 5.1.35. ¿Y por qué el índice no se puede usar? –

+0

'@Jack M.': mi publicación explica por qué. – Quassnoi

+0

'@Jack M.': ¿podrías explicar tu voto negativo? – Quassnoi

-8

Creo que transferir gran cantidad de datos de una conexión de red lenta.

En lugar de seleccionar *, seleccione solo las columnas que realmente necesita.

Si su tabla contiene campos de texto grandes que desea mostrar en el resultado, puede usar la subcadena para transferir solo los primeros caracteres/palabras del texto.

Algunos clientes admiten la compresión de los paquetes de resultados. Tal vez quieras echar un vistazo a eso.

+2

Esto se ejecuta desde localhost, devolviendo solo 100 resultados, y la mayoría de los resultados son 1 dirección de correo electrónico y un nombre. No grandes cantidades de datos, no conexiones lentas. –

Cuestiones relacionadas