У мене є запит, який поєднує декілька таблиць і виконує досить погано - оцінки рядків відключаються (в 1000 разів) і вибирається об'єднання вкладених циклів, в результаті чого відбувається багаторазове сканування таблиці. Форма запиту досить проста, виглядає приблизно так:
SELECT t1.id
FROM t1
INNER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
LEFT OUTER JOIN t4 ON t3.t4_id = t4.id
WHERE t4.id = some_GUID
Граючи з запитом, я помітив, що коли я натякаю йому на використання об'єднання Merge для одного з об'єднань, він працює в багато разів швидше. Це я можу зрозуміти - Об'єднання об'єднань є кращим варіантом даних, які об’єднуються, але SQL Server просто не оцінює його правильним вибором вкладених циклів.
Що я не повністю розумію, це те, чому цей натяк на підключення змінює всі оцінки для всіх операторів плану? Читаючи різні статті та книги, я припустив, що оцінки кардинальності виконуються до того, як план побудований, тому використання підказки не змінило б оцінок, а скоріше явно скаже SQL Server використовувати певну фізичну реалізацію приєднання.
Однак я бачу, що натяк на об'єднання змушує всі оцінки стати ідеальними. Чому це відбувається і чи є якісь загальні методи, щоб оптимізатор запитів зробив кращу оцінку без натяку - враховуючи, що статистика, очевидно, це дозволяє?
UPD: анонімізовані плани виконання можна знайти тут: https://www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan?dl=0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl = 0
Я перевірив статистику, використовувану обома запитами за допомогою TF 3604, 9292 та 9204, і ці дані однакові. Однак індекси, які скануються / шукаються, відрізняються між запитами.
Крім того, я спробував запустити запит за допомогою OPTION (FORCE ORDER)
- він працює навіть швидше, ніж використовувати об'єднання об'єднань, вибравши HASH MATCH для кожного приєднання.