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 NULLmismos resultados. - La tabla original se creó con
ANSI_PADDING OFF, pero crearla conANSI_PADDING ONno afecta a este plan. - Intenté un en
INNER JOINlugar 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



