Optimización de la búsqueda de MySQL usando “me gusta” y comodines

¿Cómo pueden las consultas como

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

estar 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 parte de un texto) por lo que no se puede realizar la búsqueda de texto completo.

Dos caminos:

(1) use 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.

¿Cuánto duran tus cadenas?

Si son relativamente cortos (por ejemplo, palabras en inglés, avg_len = 5) y tiene espacio de almacenamiento de base de datos, pruebe este enfoque:

  • Para cada palabra que desee almacenar en la tabla, en su lugar, tome todos los sufijos posibles de esa palabra. En otras palabras, sigues eliminando el primer personaje hasta que no quede nada. Por ejemplo, la palabra value da:
    • value
    • alue
    • lue
    • ue
    • e
  • Almacene 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, ha eliminado la necesidad del comodín principal (lo que permite utilizar un índice para realizar búsquedas rápidas), a costa del espacio de almacenamiento.

Costo de almacenamiento

La cantidad 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, palabra por palabra. Aquí está el factor de aumento para varios tamaños de palabras:

  • Palabra de 3 letras: (3*3/2) / 3 = 1.5
  • Palabra de 5 letras: (5*5/2) / 5 = 2.5
  • Palabra de 7 letras: (7*7/2) / 7 = 3.5
  • Palabra de 12 letras: (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 una compensación en donde dividimos ‘palabras’ (o fragmentos). Como un ejemplo del mundo real: ¿qué hacemos con los guiones? ¿Almacenamos el adjetivo de five-letter como una palabra o dos?

La compensación es la siguiente:

  • Cualquier cosa que se rompa no se puede encontrar como un solo elemento. Si almacenamos five y letter separado, la búsqueda de five-letter o five-letter fallará.
  • Cualquier cosa que no esté dividida tendrá más espacio de almacenamiento. Recuerde, el requisito de almacenamiento aumenta cuadráticamente en la longitud de la 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 five letter . (Si también quita los guiones de cualquier consulta de búsqueda, los usuarios aún pueden encontrar correctamente five-letter ).

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

Use la búsqueda de texto completo . El encabezado “Idea inicial” tiene el mismo ejemplo y conduce a la solución de ejemplo trabajado.

Y los documentos de MySQL

Editar: no se puede sintonizar en SQL. Usar funciones como LOCATE o PATINEX tampoco ayudará.

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