Індексуйте ефективність увімкнено та порівняно з десь


26

У мене дві таблиці

@T1 TABLE
(
    Id INT,
    Date DATETIME
)

@T2 TABLE
(
    Id INT,
    Date DATETIME
)

Ці таблиці мають некластеризований індекс на (Id, Date)

І я приєднуюся до цих таблиць

SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON 
    t1.Id = t2.Id
WHERE 
    t1.Date <= GETDATE()
    AND
    t2.Date <= GETDATE()

Це також можна записати як

SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON 
    t1.Id = t2.Id
    AND
    t1.Date <= GETDATE()
    AND
    t2.Date <= GETDATE()

Моє запитання, який із цих двох запитів дає кращу ефективність і чому? Або вони рівні?


1
Ви дійсно є @table variabled з некластерірованних індексу , який охоплює всі області, і не кластерний індекс? чи це просто спрощення?
Ремус Русану

1
Це надзвичайне спрощення
Ерік Бергштедт

Відповіді:


32

Вистава буде однаковою. Оптимізатор розпізнає це і створить той самий план.

З іншого боку, я б не сказав, що вони рівні. Перша форма запитання набагато легше читається та загалом очікувана.

Наприклад, за допомогою деяких таблиць, які я маю під рукою, ви можете побачити план виконання точно такий же, незалежно від того, як я пишу запит.

Ви повинні мати змогу визначити плани запитів для ваших власних таблиць та набору даних, щоб ви могли побачити, що відбувається у вашій ситуації.

SELECT * FROM salestable , custtable 
WHERE salestable.custaccount = custtable.accountnum 
AND salestable.dataareaid = custtable.dataareaid

SELECT * FROM salestable 
JOIN  custtable 
ON salestable.custaccount = custtable.accountnum 
AND salestable.dataareaid = custtable.dataareaid

SELECT * FROM salestable JOIN custtable 
ON salestable.custaccount = custtable.accountnum 
WHERE salestable.dataareaid = custtable.dataareaid

Надає ці плани виконання

введіть тут опис зображення


Я погоджуюся, першу форму читати простіше, і я таким чином полегшую, що вони рівні. Я буду використовувати цю форму лише надалі.
Ерік Бергштедт

@ErikBergstedt Я відредагував свою відповідь, ви повинні мати можливість перевірити це для власного набору даних та структури таблиці, коли ви дивитесь на плани виконання
Tom V - Команда Моніка

Так. Дякую. Я шукав лише другу думку, оскільки не знайшов відповіді.
Ерік Бергштедт

Примітка: вони САМО рівні, якщо це INNER JOIN. Якщо ви кинетесь, OUTER JOINто вони, очевидно, не такі.
Кеннет Фішер

22

Вони семантично однакові, і оптимізатору не повинно бути проблем із визнанням цього факту та створенням однакових планів.

Я схильний ставити умови, що посилаються на обидві таблиці, ONі умови, що посилаються лише на одну таблицю в WHERE.

Однак OUTER JOINSумови переміщення можуть впливати на семантику.


7

У простих випадках це буде те саме. Однак я бачив, що дуже складні запити з кількома приєднаннями мають суттєво різні плани. Недавній, над яким я працював, почав із таблиці, що містить близько 6 мільйонів рядків, приєднаних до приблизно 20 різних таблиць. Тільки перше приєднання до цієї таблиці було внутрішнім приєднанням, всі інші залишилися зовнішніми приєднаннями. Фільтр у пункті де було параметризовано приблизно так:

WHERE table1.begindate >= @startdate AND table1.enddate < @enddate 

Цей фільтр використовувався пізніше в плановому замість раніше. Коли я перемістив ці умови на перше внутрішнє з'єднання, план кардинально змінився, оскільки фільтр був застосований на початку плану, щоб обмежити набір результатів, а мій процесор і минулий час впали приблизно на 310%. Отже, як і в багатьох питаннях SQL Server, це залежить.


2
Чи можете ви додати більше деталей - можливо, скріншоти діаграм плану виконання - як ваша відповідь суперечить усім іншим?
Кенні Евітт

2
Чи показав план оптимізаційний тайм-аут?
Мартін Сміт

Як завантаження процесора можливо знизиться більш ніж на 100%?
Майкл Грін

2

Загалом, там, де ви ставите фільтри, має значення.
Хоча Том V каже, що Оптимізатор визнає, що запити однакові і придумує той самий план, що не завжди відповідає дійсності. Це залежить від того, на якій версії ви використовуєте SQL, наскільки складним є ваш запит та наскільки важливим для загальної партії оптимізатор визначає запит.

Оптимізатор може вирішити, що ця частина партії не варто витрачати достатньо часу, щоб вона змогла скласти найкращий план. Як правило, ви отримаєте кращу ефективність, якщо поставити умови, які зменшують кількість даних, над якими буде потрібно працювати в запиті ON, а не в пункті WHERE (якщо можливо, оскільки виконання цього зовнішнього з'єднання призведе до отримання декартового продукту .)

Іноді SQL Developer трохи простіше помітити фільтри в пункті WHERE, але я працював над великими таблицями, де наявність фільтрів у пункті ON скорочує години поза часом виконання.

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


1

У звичайних умовах умови фільтра можуть бути визначені або в пунктах WHERE або JOIN. Я схильний розміщувати фільтри під тим, де не може бути порушений пріоритет OUTER JOIN (див. Нижче) або якщо фільтр дуже специфічний для цієї таблиці (наприклад, TYPE = 12, щоб вказати певний підмножина рядків у таблиці).

З іншого боку, і положення ON і WHERE можуть використовуватися для визначення умов приєднання (на відміну від умов фільтра). Поки ви використовуєте лише INNER, він все одно не має значення, яким ви користуєтесь у звичайних обставинах.

Якщо ви використовуєте OUTER приєднання, однак, це може дуже змінити. Якщо, наприклад, ви вказали ВІДНІШНЕ ПРИЄДНАННЯ між двома таблицями (t1 та t2), але потім, у пункті WHERE, перейдіть, щоб вказати співвідношення eqijoin між таблицями (наприклад, t1.col = t2.col), у вас просто перетворив ВНУТРІШНЕ приєднання до ІННЕРУ! Це тому, що WHERE може бути використаний для вказівки equijoin (або, можливо, навіть OUTER приєднання, залежно від версії, використовуючи застарілий синтаксис * =), не використовуючи пункт ON, а коли WHERE вказує на внутрішній еквіоргін між таблицями, він переосмислює зовнішній ПРИЄДНАЙТЕСЬ (якщо є).

Первісне питання стосувалося фільтрів, де тип з'єднання часто не повинен бути проблемою, але приєднання також може діяти як фільтр, і в таких ситуаціях розміщення умови з'єднання, безумовно, може мати значення.


-1

З INNER JOINs це питання стилю.

Однак із зовнішніми приєднаннями стає набагато цікавіше. Ви повинні вивчити відмінності між запитами з OUTER JOINs та умовами як у пункті ON, так і в пункті WHERE. Набір результатів не завжди однаковий. Це, наприклад,

OUTER JOIN dbo.x ON a.ID = x.ID ... WHERE x.SomeField IS NOT NULL

такий же як і

INNER JOIN dbo.x ON a.ID = x.ID AND x.SomeField IS NOT NULL

8
Якщо результат різний (що, звичайно, є), у чому сенс порівняння продуктивності?
ypercubeᵀᴹ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.