2012-03-06 16 views
7

Tengo una base de datos con más de 75,000 filas con más de 500 entradas por día.¿La forma más eficiente de buscar en SQL?

Cada fila tiene un título y una descripción.

Creé una fuente RSS que le proporciona las últimas entradas para un término de búsqueda específico (por ejemplo, http://site.com/rss.rss?q=Pizza generaría un RSS para el término de búsqueda "Pizza").

Me preguntaba cuál sería la mejor manera de escribir la consulta SQL para esto. Ahora mismo tengo:

SELECT * 
FROM 'table' 
WHERE (('title' LIKE %searcherm%) OR ('description' LIKE %searcherm%)) 
LIMIT 20; 

pero el problema es que se necesita entre 2 y 10 segundos para ejecutar la consulta.

¿Hay una mejor manera de escribir la consulta, tengo que almacenar en caché los resultados (y cómo iba a hacer eso?) O gustaría cambiar algo en la velocidad de estructura de base de datos de la consulta (índices?)

+0

podría ser más rápido que el hilo individuo/desembolsar la transformación en 2 querys simples: 'seleccionar tabla donde título límite 20' luego 'seleccionar de la tabla donde descripción límite 20' cosa, entonces hacer las uniones/lista concat con su lado del servidor tech –

+0

solr, lucene, esfinge? –

Respuesta

8

Una solución relativamente simple para esto sería la incorporación de un índice FULLTEXT en estos dos campos y, posteriormente, la búsqueda mediante el uso de este índice.

ALTER TABLE table ADD FULLTEXT(title, description); 

Entonces se necesita para realizar una búsqueda, usted haría lo siguiente:

SELECT id FROM table 
WHERE MATCH (title, description) AGAINST ('keyterm'); 

Texto completo indexado de búsqueda es la solución automática incluido en la mayoría de bases de datos SQL. Es mucho más rápido comparado con hacer LIKES. Esto también está optimizado para su caso específico porque solo está interesado en términos de búsqueda de lenguaje natural.

Además, el índice de texto completo tiene algún algoritmo de limitación para detectar la relevancia. Puede leer más sobre él here

EDITAR

En la instrucción ALTER, que se perdió el nombre del índice de texto completo, que debe ser:

ALTER TABLE table ADD FULLTEXT ft_index_name(title, description); 
+0

Voy a intentar eso. ¡Gracias! – supercoolville

+0

Tenga en cuenta que esto solo funcionará con las tablas MyISAM, no con InnoDB. –

+1

Muchas gracias! Probé esto y mis búsquedas fueron 14 veces más rápidas en promedio !!!!!!! – supercoolville

-2

Algunos consejos: elimine * en su declaración seleccionada y seleccione solo los criterios de búsqueda, y asegúrese de agregar índices a las columnas que están siendo buscadas.

SELECT `title`,`description` 
FROM `table` 
WHERE `title` LIKE '%$searchterm%' OR `description` LIKE '%$searchterm%' LIMIT 25; 
+0

"Suelta el * en tu declaración seleccionada y selecciona solo los criterios buscados" - bien, ¿cómo sabes lo que quiere recuperar? –

+0

No, pero basado en su cláusula WHERE, puedo determinar que necesita al menos el título y la descripción. De todos modos, siempre es mejor especificar sus tablas en lugar del comodín, él está preguntando cómo acelerar la consulta y eliminar los comodines es el primer paso. –

+0

hay un LÍMITE 20 .. Dudo que haga una diferencia mensurable –

-2
  1. ¿Ha creado un índice para title y para description?
  2. Debería considerar Sphinx para capacidades de búsqueda de texto completo.

Gracias por el comentario Tyler.

replanteo mi respuesta:

1) Crear un índice en title y description columnas, pero la consulta se limitaría al ejemplo de abajo, y eso no es ideal para encontrar todas las filas relevantes:

SELECT * 
FROM 'table' 
WHERE title LIKE 'searcherm%' OR description LIKE 'searcherm%' 
LIMIT 20; 

2) Como han mencionado otros, use MySQL Full-Text Search, pero está limitado al motor de tabla MyISAM, ya que no está disponible para InnoDB. Sin embargo, puede mezclar motores en MySQL, por lo que puede hacer que esta tabla sea MyISAM, incluso si todas las demás tablas son InnoDB.

3) Utilice un motor externo de búsqueda de texto completo, como Sphinx. Esto le dará resultados de búsqueda más relevantes (la búsqueda de texto completo de MySQL deja mucho que desear), tendrá un mejor rendimiento y abstrae la carga de la búsqueda de texto completo de su base de datos.

+2

El índice no ayudará aquí. Como '% foo%' nunca usa un índice. Ese es su problema REAL. –

4

Probar:

SELECT * FROM table 
WHERE MATCH (title,description) AGAINST (searchterm); 

Asegúrese de que añade un índice de texto completo en el título, descripción juntos.

No intente reinventar la rueda. MATCH y AGAINST son provided by mysql para hacer exactamente eso y hacer su vida más fácil. Sin embargo, tenga en cuenta que la búsqueda de texto completo funciona en tablas MyISAM. Usted can workaround para InnoDb también.Usted puede simplemente añadir el índice FT mediante la alteración de mesa como:

ALTER TABLE table ADD FULLTEXT(title,description); 
+0

Esta es la única respuesta que funcionaría. Mencione que necesita agregar un índice de texto completo a estas columnas y debe usar tablas MyISAM. –

+0

@FrancisAvila Actualizado mi respuesta. – jerrymouse

2

Si está utilizando una consulta con LIKE '%term%' los índices no se pueden utilizar. Se pueden usar solo si utiliza una consulta como 'term%'. Piense en una libreta de direcciones con pestañas, puede encontrar contactos realmente rápidos comenzando con la letra L, pero para encontrar contactos con un on en algún lugar de la palabra, debe escanear toda la libreta de direcciones.

La mejor alternativa podría ser el uso de índices de texto completo:

CREATE FULLTEXT INDEX title_desc 
ON table (title, description) 

Y luego, en la consulta:

SELECT title, description FROM table 
WHERE MATCH (title, description) AGAINST ('+Pizza') 
0

Me gustaría ir con JohnB de o respuesta de gtr32x (Indización de texto completo). Para complementar su respuesta, hay una forma manual de crear un índice simple de texto completo que es simple y es súper rápido ...

Divida el título y la descripción en palabras clave, y colóquelos en una tabla Keywords, que tiene una clave externa para el artículo RSS original. Asegúrese de que la columna de palabras clave en Keywords esté indexada. Usted puede hacer algo como:

SELECT DISTINCT ra.* 
FROM RssArticle ra 
INNER JOIN Keywords k ON k.ArticleID = ra.ArticleID 
    WHERE k IN ('SearchTerm1', 'SearchTerm2', 'SearchTerm3') 
LIMIT 20; 

¡Y es rápido!

+0

No estoy seguro de lo que quiere decir con eso ... – supercoolville

0

pruebe una de las siguientes cuatro preguntas:

select * from myTable where concat_ws(' ',title,description) like '%pizza%'; 
select * from myTable where concat_ws(' ',title,description) regexp '.*pizza+.*'; 
select title,description from myTable where concat_ws(' ',title,description) like '%pizza%'; 
select title,description from myTable where concat_ws(' ',title,description) regexp '.*pizza+.*'; 

el punto es utilizar concat antes de buscar

+0

esto fue aproximadamente 2 veces más rápido, pero no tan rápido como ENFRENTAR EN CONTRASTE – supercoolville

Cuestiones relacionadas