2010-01-17 13 views
11

¿Cómo puede consultas comoOptimización de búsqueda de MySQL usando "como" comodines y

SELECT * FROM sometable WHERE somefield LIKE '%value%' 

ser optimizado?

El problema principal aquí es el primer comodín que impide que DBMS use el índice.

Editar: Lo que es más, el valor de algún campo es una cadena sólida (no una pieza de texto) por lo que la búsqueda de texto completo no se pudo realizar.

+1

Si necesita encontrar una subcadena en valor, es posible que su configuración de base de datos se pueda modificar para darle una mejor opción. ¿Puede proporcionar ejemplos de datos/consultas que realmente está utilizando con algún contexto? – MindStalker

Respuesta

3

Dos formas:

(1) utilice una tabla en memoria para que vaya muy rápido.

(2) cocinar un mejor índice y algoritmo de búsqueda que foo LIKE '%bar%'. No es posible hacer ninguna sugerencia al respecto sin saber más acerca de su problema.

Como ha señalado, el patrón% bar% garantiza un escaneo de tabla para cada búsqueda, lo que anula cualquier ingenio de búsqueda posible en el software de la base de datos.

4

Use Full Text Search. El encabezado "Idea inicial" tiene el mismo ejemplo y conduce a la solución de ejemplo trabajado.

And the MySQL docs

Editar: No se puede sintonizar en sí mismo SQL. Usar funciones como LOCATE o PATINEX tampoco ayudará.

+1

en realidad no necesito encontrar una palabra específica en el texto. Necesito encontrar la subcadena en valor (actualizaré la pregunta para aclarar esto). – Jonas

+0

No importa si se trata de una palabra completa o no: no * puede * optimizar esta consulta – gbn

+1

Quizás existan soluciones más complejas que simplemente optimizar la consulta para realizar este tipo de búsqueda más rápido. – Jonas

4

No supondrá una gran diferencia, dado que su problema es con el comodín, pero al no usar "SELECT *" mejorará el rendimiento de la consulta. Si no está utilizando realmente todos los campos que obtiene, eso es una ganancia y "SELECCIONAR *" hace que se disparen dos consultas, una para buscar los campos de la tabla y luego su consulta con los nombres de campo agregados.

16

¿Cuánto duran sus cadenas?

Si son relativamente corto (por ejemplo, palabras en inglés; avg_len = 5) y dispone de almacenamiento de base de datos de sobra, probar este enfoque:

  • Para cada palabra que desea almacenar en la tabla, en lugar tomar cada posible sufijo de esa palabra. En otras palabras, sigues eliminando el primer personaje hasta que no quede nada. Por ejemplo, la palabra da value:
    • value
    • alue
    • lue
    • ue
    • e
  • tienda cada uno de estos sufijos en la base de datos.
  • Ahora puede buscar subcadenas usando LIKE 'alu%' (que encontrará 'alu' como parte de 'valor').

Al almacenar todos los sufijos, que han eliminado la necesidad de que el comodín líder (que permite un índice que se utilizará para la búsqueda rápida), a costa de espacio de almacenamiento.

coste de almacenamiento

El número de caracteres necesarios para almacenar una palabra se convierte en word_len*word_len/2, es decir cuadrática en la longitud de la palabra, en función de cada palabra. Aquí está el factor de crecimiento para diferentes tamaños de palabra:

  • 3-carta palabra: (3*3/2)/3 = 1.5
  • 5-carta palabra: (5*5/2)/5 = 2.5
  • 7-carta palabra: (7*7/2)/7 = 3.5
  • 12-carta palabra: (12*12/2)/12 = 6

El número de filas requeridas para almacenar una palabra aumenta de 1 a word_len. Tenga en cuenta esta sobrecarga. Las columnas adicionales deben mantenerse al mínimo para evitar el almacenamiento de grandes cantidades de datos redundantes. Por ejemplo, un número de página en el que se encontró originalmente la palabra debería estar bien (piense en smallint sin firmar), pero los metadatos extensos de la palabra deberían almacenarse en una tabla separada por palabra, en lugar de para cada sufijo.

Consideraciones

Hay un equilibrio en donde nos separamos 'palabras' (o fragmentos). Como un ejemplo del mundo real: ¿qué hacemos con los guiones? ¿Almacenamos el adjetivo five-letter como una palabra o dos?

La compensación es el siguiente:

  • Cualquier cosa que se rompe no se puede encontrar como un único elemento. Si almacenamos five y letter por separado, la búsqueda de five-letter o fiveletter fallará.
  • Cualquier cosa que sea no dividida llevará más espacio de almacenamiento. Recuerde, el requisito de almacenamiento aumenta cuadráticamente en la longitud de palabra.

Para su comodidad, es posible que desee eliminar el guión y almacenar fiveletter. La palabra ahora se puede encontrar buscando five, letter y fiveletter. (Si también quita los guiones de cualquier consulta de búsqueda, los usuarios pueden encontrar con éxito five-letter.)

Finalmente, hay maneras de almacenar arreglos de sufijos que no requieren demasiada sobrecarga, pero aún no estoy seguro de si se traducen bien. a las bases de datos.

+3

Esta es una ** muy ** buena respuesta y es la única respuesta que resuelve el problema. (Es cierto que tiene la limitación de que sus cadenas deben ser lo suficientemente cortas para que no le importe multiplicar el número de filas por la longitud promedio de la cuerda, pero eso probablemente sea inevitable). – antinome

Cuestiones relacionadas