Как я могу оптимизировать объединение с многотабличной сортировкой в ​​T-SQL? - PullRequest
4 голосов
/ 15 июля 2011

Как я могу оптимизировать следующий запрос?

   SELECT TOP 50 *
     FROM A 
LEFT JOIN B ON A.b_id = B.id 
 ORDER BY A.number, B.name DESC

Я создал некластеризованный индекс (A.number asc, A.creation_date desc), который включает в себя все столбцы из A и другой не-clustered индекс на B.origination_date desc, который включает в себя все столбцы из B (кроме текстовых столбцов).Ни один из этих индексов не используется, в соответствии с фактическим планом выполнения из SQL Server Management Studio.

По-видимому, причиной снижения производительности является сортировка B.origination_date.Когда я проверяю фактический план выполнения в SQL Server Management Studio, я вижу, что «Top N Sort» в этих трех полях занимает 91% времени выполнения.Если я отбрасываю сортировку на B.origination_date, запрос завершается почти мгновенно, используя индекс для A.

Edit: Обновлен запрос, чтобы предоставить лучший, более простой пример.

Ответы [ 3 ]

5 голосов
/ 15 июля 2011

Я бы предположил, A.number, как '%%' , это ваша проблема. Что это должно сделать? Вы не должны использовать подобное с подстановочным знаком в качестве первого символа, если вы хотите использовать индексы. Поскольку это стоит, это, кажется, фильтрует даром, поскольку между символами подстановки ничего нет.

1 голос
/ 16 июля 2011

Поскольку вы сортируете столбцы из двух разных таблиц, SQL Server должен объединить таблицы и затем выполнить сортировку. После объединения таблиц индексы отдельных таблиц не помогают при сортировке. Индексированное представление может быть вашей лучшей ставкой.

1 голос
/ 15 июля 2011

Без практического доступа сложно найти сложные и быстрые решения.Некоторые идеи и предложения:

Без объединения таблицы B все, что нужно сделать SQL (с индексом A.Number), - это пройти до тех пор, пока не найдет первые 50 строк, соответствующих вашему шаблону.Если значения «Number» относительно уникальны (не так много дубликатов (это количество элементов)), то иметь значение Creation_Date в индексе также мало смысла.

Почему левое внешнее соединение с B?Это от одного до [нуля или одного] или от одного до [нуля или многих]?Если количество элементов низкое (много дубликатов в A), то объединение требуется, чтобы четко найти «первые 50», иначе можно было бы подумать, что объединение не повлияет на производительность, кроме необходимости выполнить объединение).Я не вижу никакого индекса на B (кроме идентификатора столбца), который имеет значение здесь.Хм, у вас есть индекс на B.Id, верно?Если нет, то это может сильно замедлить ход событий (конечно, при условии, что B имеет значительное количество строк).

Для получения более подробных сведений я хотел бы рассмотреть количество элементов объединения и порядка по столбцам,и очень внимательно изучите план выполнения запроса «с соединением».


Дополнения

Если A имеет низкое количество элементов (много дубликатов), то оптимизатор запросов может «подумать»что для решения порядка потребуется много B.Id (что необходимо сделать, чтобы найти Top 50).Это может объяснить, почему он делает то, что делает.

Если они будут давать 100% эквивалентные результаты, я бы рекомендовал заменить ЛЕВОЕ соединение на ВНУТРЕННЕЕ.В целом, планы запросов могут стать намного проще, если действуют более строгие условия объединения.

...