Для помірно складного запиту, який я намагаюся оптимізувати, я помітив, що видалення TOP n
пункту змінює план виконання. Я б здогадався, що коли запит включає TOP n
в себе двигун бази даних, він би запустив запит, ігноруючи TOP
застереження, а потім наприкінці просто зменшить цей результат, встановлений на n кількість рядків, які запитували. Графічний план виконання, схоже, вказує, що це так - TOP
це "останній" крок. Але, здається, там відбувається більше.
Моє запитання полягає в тому, як (і навіщо) пункт TOP n впливає на план виконання запиту?
Ось спрощена версія того, що відбувається в моєму випадку:
Запит відповідає рядкам із двох таблиць, A і B.
Без TOP
пункту, оптимізатор розраховує, що з таблиці А буде розміщено 19 к рядків та 46 к рядків таблиці B. Фактична кількість рядків, що повертаються, становить 16 к для А та 13 к для Б. Хеш-матч використовується для приєднання цих двох наборів результатів для всього 69 рядків (тоді застосовується сортування). Цей запит відбувається дуже швидко.
Коли я додаю, TOP 1001
оптимізатор не використовує хеш-відповідність; натомість він спочатку сортує результати з таблиці A (така ж оцінка / фактична 19k / 16k) та робить вкладений цикл проти таблиці B. Орієнтовна кількість рядків для таблиці B зараз 1, і дивно, що TOP n
безпосередньо впливає на Орієнтовна кількість страт (пошук індексу) проти B - вона, як видається, завжди дорівнює 2n + 1 , або в моєму випадку 2003. Ця оцінка відповідно змінюється, якщо я змінюсь TOP n
. Звичайно, оскільки це вкладене об'єднання, фактична кількість виконань становить 16 к (кількість рядків з таблиці А), і це уповільнює запит.
Справжній сценарій є трохи складнішим, але це фіксує основну ідею / поведінку. В обох таблицях здійснюється пошук за допомогою індексів. Це видання SQL Server 2008 R2 Enterprise.
FAST num_rows
підказка щодо запиту.
ORDER BY
пункт. ДодаванняTOP
змін там, де в плані відбувається такий сорт, але мене більше хвилює те, як це впливає на кількість виконання покажчиків індексу проти таблиці B ... (звичайно, вони можуть бути пов'язані - я не знаю)