У мене дві таблиці з однаково названими, типізованими та індексованими стовпцями ключів. Один з них має унікальний кластерний індекс, інший - не унікальний .
Тестова установка
Сценарій налаштування, включаючи деякі реалістичні статистичні дані:
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;
Запрошення
Коли я приєднуюся до цих двох таблиць на клавішних клавішах, я очікую приєднання МНОГО одного до багатьох, наприклад:
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';
Цей план запитів я хочу:
(Незважаючи на попередження, вони мають відношення до підробленої статистики.)
Однак якщо я зміню порядок стовпців навколо приєднання, так:
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';
... це відбувається:
Очевидно, оператор Sort упорядковує потоки відповідно до заявленого порядку з'єднання, тобто c, a, b, d, e, f, g, h
додає операцію блокування до мого плану запитів.
Речі, на які я дивився
- Я спробував змінити стовпці на
NOT NULL
однакові результати. - Оригінальну таблицю було створено за допомогою
ANSI_PADDING OFF
, але її створення за допомогоюANSI_PADDING ON
цього плану не впливає. - Я спробував
INNER JOIN
замість цьогоLEFT JOIN
, без змін. - Я виявив це на SP2 Enterprise 2014 року, створив репрограму для розробника 2017 року (поточний CU).
- Видалення пункту WHERE з провідного стовпця індексу генерує хороший план, але це на зразок впливає на результати .. :)
Нарешті, ми переходимо до питання
- Це навмисно?
- Чи можу я усунути сортування, не змінюючи запит (який є кодом постачальника, так що я дійсно краще не ...). Я можу змінити таблицю та індекси.