SQL Server - índice en una columna calculada?
-
19-09-2019 - |
Pregunta
Me estoy uniendo a una tabla de docenas de diferentes veces, y cada vez, unirse (o filtro) en base a los resultados de una subcadena de una de las columnas (que es una cadena, pero dejó acolchado con ceros, y no me importa acerca de los cuatro últimos dígitos). Como resultado, a pesar de que esta columna está indexada y mi consulta sería utilizar el índice, se hace un recorrido de tabla porque la subcadena en sí no está indexado, por lo que SQL Server tiene que calcular que por cada fila antes, ya que está uniendo.
Estoy buscando alguna idea sobre la forma de acelerar este proceso. Actualmente, hay una vista sobre la mesa (Es un "SELECT * FROM", sólo para dar a la mesa un nombre descriptivo), y estoy considerando la adición de una columna a la vista que se calcula, y después de que la indexación. Estoy abierto a otras sugerencias, sin embargo - cualquier pensamiento
?más detalle: Debería haber compartido esta para empezar. La tabla recibe la replicación de nuestro sistema de facturación, por lo que la edición de la tabla subyacente para agregar una columna calculada no es una opción. Cualquier columna calculada tendría que ser añadido a la vista sobre la mesa. Además, los ceros a la izquierda no son siempre ceros a la izquierda -. A veces son otros datos que no estoy interesado en supongo que la pregunta real es " ¿Cómo puedo unirme a los datos en el medio de una columna, mientras VARCHAR también haciendo uso de un índice? búsqueda de texto completo? "
Aclaración de mi ejemplo Estoy simplificando, pero en esencia, digamos que estoy tratando de buscar valores en una columna con los siguientes valores:
00000012345MoreStuff
00000012345Whatever
19834212345
Houses12345837443GGD
00000023456MoreStuff
Estoy interesado en las filas donde SUBSECUENCIA (7,5) = "12345", por lo que me gustaría filas 1-4, pero no la fila 5. Lo que estoy proponiendo es la adición de una columna a mi "SELECT * "opinión de que tiene esta subcadena en ella, y luego la indexación basada en eso. ¿Eso hace más sentido?
Solución
Asumiendo que tiene sus campos en este formato:
00Data0007
000000Data0011
0000Data0015
, puede hacer lo siguiente:
-
Crear una columna calculada:
ndata AS RIGHT(REVERSE(data), LEN(data) - 4)
Esto transformará sus columnas en los siguientes:
ataD00 ataD000000 ataD0000
-
Crear un índice en esa columna
-
El tema esta consulta para buscar el
Data
cadena:SELECT * FROM mytable WHERE ndata LIKE N'ataD%' AND SUBSTRING(ndata, LEN(N'ataD') + 1, LEN(ndata)) = REPLICATE('0', LEN(ndata) - LEN('ataD'))
La primera condición utilizará un índice para el filtrado grueso.
El segundo se asegurará de que todos los personajes principales (que se convirtieron en los caracteres finales en la columna calculada) no son más que ceros.
Vea esta entrada en mi blog para los detalles de rendimiento:
Actualizar
Si lo que desea es un índice en SUBSTRING
sin cambiar su esquema, la creación de un punto de vista es una opción.
CREATE VIEW v_substring75
WITH SCHEMABINDING
AS
SELECT s.id, s.data, SUBSTRING(data, 7, 5) AS substring75
FROM mytable
CREATE UNIQUE CLUSTERED INDEX UX_substring75_substring_id ON (substring75, id)
SELECT id, data
FROM v_substring75
WHERE substring75 = '12345'
Otros consejos
Añadir una columna calculada a su mesa y crear un índice en esta columna.
ALTER TABLE MyTable
Add Column CodeHead As LEFT(Code,Len(Code)-4)
A continuación, crear un índice en esto.
CREATE INDEX CodeHeadIdx ON MyTable.CodeHead
¿Puede volver a la frase con su búsqueda en términos de una declaración como 'algo%'? (Esto es aplicable a un índice)
Cambiar la columna a dos columnas - los datos se inscribe en el extra y 4 caracteres. El uso de partes de una columna ralentiza las cosas a medida que hve visto