У меня есть две таблицы с одинаковыми именованными, типизированными и индексированными ключевыми столбцами. Один из них имеет уникальный кластеризованный индекс, другой - неуникальный .
Тестовая настройка
Сценарий установки, включая некоторые реалистичные статистические данные:
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;
Репро
Когда я объединяю эти две таблицы по их ключам кластеризации, я ожидаю соединения MERGE один-ко-многим, например:
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
, без изменений. - Я обнаружил это в 2014 году с пакетом обновления 2 (SP2 Enterprise), создал репродукцию для разработчика в 2017 году (текущий CU).
- Удаление предложения WHERE в ведущем столбце индекса создает хороший план, но это как бы влияет на результаты .. :)
Наконец, мы подошли к вопросу
- Это намеренно?
- Могу ли я исключить сортировку без изменения запроса (который является кодом поставщика, поэтому я бы предпочел не делать этого ...). Я могу изменить таблицу и индексы.
источник