2010-01-11 41 views
29

Tengo una tabla MySQL para la cual hago frecuentes consultas SELECT x, y, z FROM table WHERE x LIKE '%text%' OR y LIKE '%text%' OR z LIKE '%text%'. ¿Algún tipo de índice ayudaría a acelerar las cosas?Cómo acelerar SELECT .. LIKE consultas en MySQL en varias columnas?

Hay unos pocos millones de registros en la tabla. Si hay algo que acelere la búsqueda, ¿afectaría seriamente el uso del disco por los archivos de la base de datos y la velocidad de las declaraciones INSERT y DELETE? (Sin UPDATE se realiza cada vez)

actualización: Rápidamente después de publicar, he visto una gran cantidad de información y discusión acerca de la forma en LIKE se utiliza en la consulta; Me gustaría señalar que la solución debe usar LIKE '%text%' (es decir, el texto que estoy buscando se antepone y se agrega con un% comodín). La base de datos también tiene que ser local, por muchas razones, incluida la seguridad.

+4

Piénselo de esta manera, no es una analogía perfecta, pero demuestra el punto. Considere un libro con un índice de palabras en la parte posterior. Si desea buscar una palabra simple o incluso palabras que comiencen con las mismas primeras letras, no hay problema. Considere lo que sucede cuando quiere usar ese índice de libros para buscar todas las palabras que contienen las letras "exe" en cualquier parte de la palabra. El índice es bastante inútil y también podría leer el libro real buscando esas palabras. Ese es aproximadamente el problema que está imponiendo en mySQL. – JohnFx

Respuesta

51

Un índice no aceleraría la consulta, porque los índices de columnas textuales funcionan indexando N caracteres comenzando desde la izquierda. Cuando le GUSTA '% text%' no puede usar el índice porque puede haber un número variable de caracteres antes del texto.

Lo que debe hacer es no utilizar una consulta como esa en absoluto. En su lugar, debe usar algo como FTS (Búsqueda de texto completo) que MySQL admite para tablas MyISAM. También es muy fácil crear dicho sistema de indexación para las tablas que no son MyISAM, solo necesita una tabla de índice separada donde almacene palabras y sus ID relevantes en la tabla actual.

+7

Debo agregar que desde MySQL 5.6, la búsqueda de texto completo también está disponible para InnoDB. – Sergio

+0

. Sin embargo, en algunos casos no es posible realizar una búsqueda de texto completo, como ocurre con los idiomas ideográficos. https://dev.mysql.com/doc/refman/5.7/en/fulltext-restrictions.html –

9

Un índice puede no ser utilizado para acelerar las consultas, donde los criterios de búsqueda se inicia con un comodín:

LIKE '%text%'

Un índice puede (y podría ser, dependiendo de la selectividad) que se utiliza para términos de búsqueda de la forma:

LIKE 'text%'

14

un índice no ayudará a juego de texto con un carácter comodín líder, un índice puede ser utilizado para :

LIKE 'text%' 

Pero supongo que no será suficiente. Para este tipo de consulta, debería estar buscando un proveedor de búsqueda de texto completo si desea escalar la cantidad de registros que puede buscar. Mi proveedor preferido es Sphinx, muy completo/rápido, etc. También vale la pena echarle un vistazo a Lucene. Un índice de texto completo en una tabla MyISAM también funcionará, pero en última instancia buscar MyISAM para cualquier base de datos que tenga una cantidad significativa de escrituras no es una buena idea.

+0

En MySQL 5.6 y versiones posteriores, también se pueden usar con tablas InnoDB. https://dev.mysql.com/doc/refman/5.7/en/fulltext-restrictions.html –

7

Yo agregaría que en algunos casos puede acelerar la consulta usando un índice junto con like/rlike si el campo que está mirando a menudo está vacío o contiene algo constante.

En ese caso, parece que puede limitar las filas que se visitan utilizando el índice agregando una cláusula "y" con el valor fijo.

Intenté esto para buscar 'etiquetas' en una tabla enorme que generalmente no contiene muchas etiquetas.

SELECT * FROM objects WHERE tags RLIKE("((^|,)tag(,|$))" AND tags!=''

Si usted tiene un índice en las etiquetas se verá que se utiliza para limitar las filas que están siendo buscadas.

+0

Esta es sorprendentemente una muy buena alternativa, pude indexar la columna de esta manera. – Kennysmoothx

6

Quizás puedas intentar actualizar mysql5.1 a mysql5.7.

Tengo alrededor de 70,000 registros. Y ejecutar SQL siguiente:

select * from comics where name like '%test%'; 

Se necesita 2000ms en mysql5.1. Y toma 200ms en mysql5.7 o mysql5.6.

Cuestiones relacionadas