Pude reproducir un problema de rendimiento de la consulta que describiría como inesperado. Estoy buscando una respuesta que se centre en lo interno.
En mi máquina, la siguiente consulta realiza un escaneo de índice agrupado y tarda aproximadamente 6,8 segundos de tiempo de CPU:
SELECT ID1, ID2
FROM two_col_key_test WITH (FORCESCAN)
WHERE ID1 NOT IN
(
N'1', N'2',N'3', N'4', N'5',
N'6', N'7', N'8', N'9', N'10',
N'11', N'12',N'13', N'14', N'15',
N'16', N'17', N'18', N'19', N'20'
)
AND (ID1 = N'FILLER TEXT' AND ID2 >= N'' OR (ID1 > N'FILLER TEXT'))
ORDER BY ID1, ID2 OFFSET 12000000 ROWS FETCH FIRST 1 ROW ONLY
OPTION (MAXDOP 1);
La siguiente consulta realiza una búsqueda de índice agrupado (la única diferencia es eliminar la FORCESCAN
sugerencia) pero toma aproximadamente 18.2 segundos de tiempo de CPU:
SELECT ID1, ID2
FROM two_col_key_test
WHERE ID1 NOT IN
(
N'1', N'2',N'3', N'4', N'5',
N'6', N'7', N'8', N'9', N'10',
N'11', N'12',N'13', N'14', N'15',
N'16', N'17', N'18', N'19', N'20'
)
AND (ID1 = N'FILLER TEXT' AND ID2 >= N'' OR (ID1 > N'FILLER TEXT'))
ORDER BY ID1, ID2 OFFSET 12000000 ROWS FETCH FIRST 1 ROW ONLY
OPTION (MAXDOP 1);
Los planes de consulta son bastante similares. Para ambas consultas hay 120000001 filas leídas del índice agrupado:
Estoy en SQL Server 2017 CU 10. Aquí hay un código para crear y completar la two_col_key_test
tabla:
drop table if exists dbo.two_col_key_test;
CREATE TABLE dbo.two_col_key_test (
ID1 NVARCHAR(50) NOT NULL,
ID2 NVARCHAR(50) NOT NULL,
FILLER NVARCHAR(50),
PRIMARY KEY (ID1, ID2)
);
DROP TABLE IF EXISTS #t;
SELECT TOP (4000) 0 ID INTO #t
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
OPTION (MAXDOP 1);
INSERT INTO dbo.two_col_key_test WITH (TABLOCK)
SELECT N'FILLER TEXT' + CASE WHEN ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) > 8000000 THEN N' 2' ELSE N'' END
, ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
, NULL
FROM #t t1
CROSS JOIN #t t2;
Espero una respuesta que haga más que solo informes de pila de llamadas. Por ejemplo, puedo ver que sqlmin!TCValSSInRowExprFilter<231,0,0>::GetDataX
toma significativamente más ciclos de CPU en la consulta lenta en comparación con la rápida:
En lugar de detenerme allí, me gustaría entender qué es eso y por qué hay una diferencia tan grande entre las dos consultas.
¿Por qué hay una gran diferencia en el tiempo de CPU para estas dos consultas?