Estoy usando MS SQL y tengo que ejecutar varias consultas en la misma tabla con diferentes criterios. Al principio ejecuté cada consulta en la tabla original, aunque todas comparten algo de filtrado (es decir, Fecha, estado). Esto tomó mucho tiempo (alrededor de 2 minutos).
Hay duplicados en las filas de datos y todos los índices NO ESTÁN AGRUPADOS. Solo estoy interesado en 4 columnas para mis criterios y el resultado debería mostrar solo el recuento, para todas las consultas.
columnas necesarias: TABLE
, FIELD
, AFTER
, DATE
, y hay un índice en cada uno de DATE
y TABLE
.
Después de crear una tabla temporal con solo los campos que necesito, se redujo a 1:40 minutos, lo que sigue siendo muy malo.
CREATE TABLE #TEMP
(
TABLE VARCHAR(30) NULL,
FIELD VARCHAR(30) NULL,
AFTER VARCHAR(1000) NULL,
DATE DATETIME,
SORT_ID INT IDENTITY(1,1)
)
CREATE CLUSTERED INDEX IX_ADT ON #TEMP(SORT_ID)
INSERT INTO #TEMP (TABLE, FIELD, AFTER, DATE)
SELECT TABLE, FIELD, AFTER, DATE
FROM mytbl WITH (NOLOCK)
WHERE TABLE = 'OTB' AND
FIELD = 'STATUS'
Ejecutando esto -> (216598 filas afectadas)
Como no todas las consultas dependen del intervalo de fechas, no lo incluí en la consulta. El problema es que solo lleva más de 1 minuto insertarlo . El inserto anterior tomó 1:19 minutos
Quiero ejecutar algo como esto para varias consultas:
SELECT COUNT(*) AS COUNT
FROM #TEMP
WHERE AFTER = 'R' AND
DATE >= '2014-01-01' AND
DATE <= '2015-01-01'
Es un problema con la inserción más que el de la selección, pero la temperatura tiene muchas menos filas que la tabla original, lo que podría ser mejor que recorrer la tabla varias veces.
¿Cómo puedo optimizar esto?
EDITAR
He eliminado el ID de clasificación, pensé que el problema era principalmente con la selección y no con la inserción. Fue una suposición.
No puedo crear un único en ningún índice ya que no hay campos o filas únicos.
Estoy usando SQL Server 2012.
Información de la tabla : es un montón y tiene el siguiente uso de espacio:
name rows reserved data index_size unused
mytbl 24869658 9204568 KB 3017952 KB 5816232 KB 370384 KB
SELECT COUNT(*) AS COUNT FROM original_table WHERE AFTER = 'R' AND DATE >= '2014-01-01' AND DATE < '2015-01-01'
, ¿por qué no intenta optimizar cada (consulta) por separado? ¿No está permitido agregar índices a la tabla?TABLE
yFIELD
de la#temp
tabla (después de todo, todas las filas tienenTABLE = 'OTB' AND FIELD = 'STATUS'
para la tabla temporal específica).CREATE TABLE
declaración). El voto negativo fue porque la pregunta no estaba clara.Respuestas:
La pregunta es principalmente sobre cómo optimizar la instrucción select:
Eliminando las proyecciones redundantes y agregando el supuesto
dbo
esquema:Sin un índice como
([TABLE],[FIELD]) INCLUDE ([AFTER],[DATE])
SQL Server tiene dos opciones principales:[TABLE] = 'OTB'
y[FIELD] = 'STATUS'
(usandoIDX6
), luego realice una búsqueda de montón (RID) por fila para recuperar las columnas[AFTER]
y[DATE]
.Si el optimizador elige una exploración de montón o búsqueda de índice con búsqueda RID depende de la selectividad estimada de los predicados
[TABLE] = 'OTB'
y[FIELD] = 'STATUS'
. Verifique si el número estimado de filas de la búsqueda coincide con la realidad. Si no, actualice sus estadísticas. Pruebe la consulta con una sugerencia de tabla que fuerce el uso del índice, si esa condición es razonablemente selectiva . Si el optimizador está eligiendo actualmente la búsqueda de índice, pruebe el rendimiento con unaINDEX(0)
o unaFORCESCAN
pista para escanear el montón.Más allá de eso, podría intentar mejorar un poco el escaneo del montón eliminando parte del espacio no utilizado (370 MB). En SQL Server 2008, esto se puede hacer reconstruyendo el montón. El espacio no utilizado en los montones a menudo es el resultado de eliminaciones realizadas sin tomar un bloqueo de tabla (sin un bloqueo de tabla, las páginas vacías no se desasignan de un montón). Las tablas que experimentan eliminaciones frecuentes a menudo se almacenan mejor como una tabla agrupada por este motivo.
El rendimiento de la exploración de almacenamiento dinámico depende de la cantidad de la tabla almacenada en la memoria, la cantidad que debe leerse desde el disco, la capacidad de las páginas, la velocidad del almacenamiento persistente, si la exploración es de E / S o de CPU ( el paralelismo puede ayudar).
Si el rendimiento sigue siendo inaceptable después de haber investigado todo lo anterior, intente presentar un nuevo índice. Si está disponible en su versión de SQL Server, un posible índice filtrado para la consulta dada sería:
También considere la compresión del índice, si está disponible y es beneficioso. Sin un nuevo índice de algún tipo, hay relativamente poco que pueda hacer para mejorar el rendimiento de la consulta dada.
fuente
IDX6 nonclustered located on PRIMARY TABLE, FIELD
. ¿Quizás esto cambiaría las cosas que mencionaste?Creo que hay un caso para cambiar los índices aquí porque:
Este también sería un buen caso de uso para los índices de almacén de columnas no agrupados introducidos en SQL Server 2012, es decir, resumir / agregar algunas columnas en una tabla grande con muchas columnas.
Aunque estos índices tienen el efecto secundario de hacer que la tabla sea de solo lectura (con la excepción del cambio de partición), pueden transformar el rendimiento de las consultas agregadas en las condiciones adecuadas. El aspecto de solo lectura se puede administrar, ya sea soltando y recreando el índice o los datos de cambio de partición simple en la tabla.
Configuré una plataforma de prueba simple para imitar su configuración, y vi una buena mejora en el rendimiento:
Mis resultados, 6 segundos v 0.08 segundos:
En resumen, intente crear un caso con su jefe para cambiar los índices o al menos crear algún tipo de proceso nocturno en el que estos registros se graben en una tabla / base de datos de solo lectura donde pueda hacer su trabajo y agregue indexación apropiado para esa carga de trabajo.
fuente