Pregunta

Tenemos una consulta que se ejecuta en una tabla bastante grande que desafortunadamente necesita usar LIKE '% ABC%' en un par de campos varchar para que el usuario pueda buscar nombres parciales, etc. SQL Server 2005

¿Sería útil agregar un índice en estos campos varchar en términos de seleccionar el rendimiento de la consulta cuando se usa LIKE o básicamente ignora los índices y realiza un análisis completo en esos casos?

¿Hay otras formas posibles de mejorar el rendimiento al usar LIKE?

¿Fue útil?

Solución

Solo si agrega búsqueda de texto completo a esas columnas y usa las capacidades de consulta de texto completo de SQL Server.

De lo contrario, no, un índice no ayudará.

Otros consejos

Potencialmente puede ver mejoras en el rendimiento al agregar índices, depende mucho de los detalles :)

¿Cuánto del tamaño total de la fila son sus columnas predicadas? ¿Cuántas filas esperas que coincidan? ¿Necesita devolver todas las filas que coinciden con el predicado, o solo las 1 filas superiores o n superiores?

Si está buscando valores con alta selectividad / unicidad (tan pocas filas para devolver), y las columnas predicadas son una porción más pequeña del tamaño completo de la fila, un índice podría ser bastante útil. Seguirá siendo un escaneo, pero su índice se ajustará a más filas por página que la tabla de origen.

Aquí hay un ejemplo donde el tamaño total de la fila es mucho mayor que el tamaño de la columna para buscar:

create table t1 (v1 varchar(100), b1 varbinary(8000))
go
--add 10k rows of filler
insert t1 values ('abc123def', cast(replicate('a', 8000) as varbinary(8000)))
go 10000
--add 1 row to find
insert t1 values ('abc456def', cast(replicate('a', 8000) as varbinary(8000)))
go

set statistics io on 
go
select * from t1 where v1 like '%456%'
--shows 10001 logical reads

--create index that only contains the column(s) to search across
create index t1i1 on t1(v1)
go
select * from t1 where v1 like '%456%'
--or can force to 
--shows 37 logical reads

Si observa el plan de ejecución real, puede ver que el motor escaneó el índice e hizo una búsqueda de marcadores en la fila correspondiente. O puede decirle al optimizador directamente que use el índice, si no hubiera decidido usar este plan solo: seleccione * de t1 con (index (t1i1)) donde v1 como '% 456%'

Si tiene un montón de columnas para buscar en unas pocas que son altamente selectivas, podría crear múltiples índices y utilizar un enfoque de reducción. P.ej. primero determine un conjunto de ID (o cualquiera que sea su PK) de su índice altamente selectivo, luego busque sus columnas menos selectivas con un filtro contra ese pequeño conjunto de PK.

Si siempre necesita devolver un gran conjunto de filas, seguramente estaría mejor con un escaneo de tabla.

Por lo tanto, las posibles optimizaciones dependen mucho de los detalles de la definición de su tabla y la selectividad de sus datos.

HTH! -Adrian

La única otra forma (además de usar la indexación de texto completo) para mejorar el rendimiento es usar " LIKE ABC% " - no agregue el comodín en ambos extremos del término de búsqueda; en ese caso, un índice podría funcionar.

Si sus requisitos son tales que debe tener comodines en ambos extremos del término de búsqueda, no tiene suerte ...

Marc

Al igual que '% ABC%' siempre se realizará un escaneo completo de la tabla. No hay forma de evitar eso.

Tienes un par de enfoques alternativos. En primer lugar, la búsqueda de texto completo, está realmente diseñado para este tipo de problema, así que lo miraría primero.

Alternativamente, en algunas circunstancias, podría ser apropiado desnormalizar los datos y preprocesar los campos de destino en tokens apropiados, luego agregar estos posibles términos de búsqueda en una tabla de búsqueda separada para muchos. Por ejemplo, si mis datos siempre consistieran en un campo que contenga el patrón 'AAA / BBB / CCC' y mis usuarios estuvieran buscando en BBB, entonces lo tokenizaría al insertar / actualizar (y eliminar al eliminar). Este también sería uno de esos casos en los que sería preferible utilizar disparadores, en lugar del código de la aplicación, mucho .

Debo enfatizar que esta no es realmente una técnica óptima y solo debe usarse si los datos coinciden con el enfoque y, por alguna razón, no desea utilizar la búsqueda de texto completo (y el rendimiento de la base de datos por el estilo) escanear realmente es inaceptable). También es probable que produzca dolores de cabeza de mantenimiento más adelante.

crea estadísticas en esa columna. sql server 2005 ha optimizado la búsqueda en cadena para que pueda beneficiarse de eso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top