TSQL Чому Top швидше зі змінною?


10

Вранці всі,

Я працюю над деяким помірно складним sql, щоб "отримати" деякі дані з бази даних сторонніх товарів, щоб відобразити їх у наших власних додатках.

Я додав у select, щоб отримати верхню запис із таблиці в підзапиті (якщо це має сенс)

запит знадобився майже 3 хвилини, щоб повернути кінцевий набір результатів із 100 записів за допомогою

SELECT TOP 1 ...

У мене в Інтернеті з’ясувались вдосконалення того, що я намагався досягти, і було запропоновано змінити свій вибір, щоб використовувати змінну, як показано нижче

DECLARE @topCount INT
SET @topCount = 1

SELECT TOP (@topCount) ...

Це вимагало того ж запиту від 3 хвилин до 1 секунди, що чудово!

Але чи може хтось пояснити, чому це так.

Відповіді:


14

Коли ви робите top 1запит, оптимізатор запитів створить план, який будується для отримання 1 ряду якомога швидше.

Коли ви використовуєте локальну змінну, значення змінної невідомо оптимізатору, і замість цього будується план, оптимізований для отримання 100 рядків якнайшвидше.

У вашому випадку план запитів, згенерований із ціллю рядка 100, є кращим планом використання, навіть якщо вам потрібно лише один рядок.

Для перевірки ви можете спробувати додати option (recompile)до запиту змінну. У цьому випадку SQL Server використовуватиме поточне значення @topCountяк рядкової цілі, і оскільки це 1, ви повинні отримати повільний план.


Я розумію різницю в плані, але мене дивує, що отримання 1 ряду може бути повільніше, ніж отримання 100 рядків. Я думаю, що якби план 100 рядків працював найкраще, SQL Server використовував би той самий план top 1.
Брендон

@Brandon не отримує 100 рядків, лише будує план виконання з припущенням, що 100 рядків - це те, що потрібно. Виконання завершується, коли знайдено 1 рядок.
Мікаель Ерікссон

Перевірка того, що відрізняється від плану виконання у цих випадках, ймовірно, допоможе зрозуміти, у чому полягає проблема у вершині 1.
James Z
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.