Tengo dos tablas con columnas de clave con nombres, tipos e índices idénticos. Uno de ellos tiene un índice agrupado único , el otro tiene un índice no único .
La configuración de prueba
Script de configuración, que incluye algunas estadísticas realistas:
DROP TABLE IF EXISTS #left;
DROP TABLE IF EXISTS #right;
CREATE TABLE #left (
a char(4) NOT NULL,
b char(2) NOT NULL,
c varchar(13) NOT NULL,
d bit NOT NULL,
e char(4) NOT NULL,
f char(25) NULL,
g char(25) NOT NULL,
h char(25) NULL
--- and a few other columns
);
CREATE UNIQUE CLUSTERED INDEX IX ON #left (a, b, c, d, e, f, g, h)
UPDATE STATISTICS #left WITH ROWCOUNT=63800000, PAGECOUNT=186000;
CREATE TABLE #right (
a char(4) NOT NULL,
b char(2) NOT NULL,
c varchar(13) NOT NULL,
d bit NOT NULL,
e char(4) NOT NULL,
f char(25) NULL,
g char(25) NOT NULL,
h char(25) NULL
--- and a few other columns
);
CREATE CLUSTERED INDEX IX ON #right (a, b, c, d, e, f, g, h)
UPDATE STATISTICS #right WITH ROWCOUNT=55700000, PAGECOUNT=128000;
La repro
Cuando uní estas dos tablas en sus claves de agrupación, espero una unión MERGE de uno a muchos, así:
SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
l.a=r.a AND
l.b=r.b AND
l.c=r.c AND
l.d=r.d AND
l.e=r.e AND
l.f=r.f AND
l.g=r.g AND
l.h=r.h
WHERE l.a='2018';
Este es el plan de consulta que quiero:
(No importa las advertencias, tienen que ver con las estadísticas falsas).
Sin embargo, si cambio el orden de las columnas en la unión, así:
SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
l.c=r.c AND -- used to be third
l.a=r.a AND -- used to be first
l.b=r.b AND -- used to be second
l.d=r.d AND
l.e=r.e AND
l.f=r.f AND
l.g=r.g AND
l.h=r.h
WHERE l.a='2018';
... esto pasa:
El operador Ordenar parece ordenar las secuencias de acuerdo con el orden declarado de la unión, es decir c, a, b, d, e, f, g, h
, que agrega una operación de bloqueo a mi plan de consulta.
Cosas que he visto
- Intenté cambiar las columnas a los
NOT NULL
mismos resultados. - La tabla original se creó con
ANSI_PADDING OFF
, pero crearla conANSI_PADDING ON
no afecta a este plan. - Intenté un en
INNER JOIN
lugar deLEFT JOIN
, sin cambios. - Lo descubrí en una empresa SP2 2014, creé una reproducción en un desarrollador 2017 (CU actual).
- Eliminar la cláusula WHERE en la columna de índice inicial genera el buen plan, pero afecta los resultados ... :)
Finalmente, llegamos a la pregunta.
- ¿Es esto intencional?
- ¿Puedo eliminar el tipo sin cambiar la consulta (que es el código del proveedor, por lo que realmente prefiero no ...). Puedo cambiar la tabla y los índices.
fuente