Оцінка порівняно з фактичним планом запиту з викликами функцій


11

У мене є цей запит на SQL сервері, запит реплікації злиття:

SELECT DISTINCT
    b.tablenick,
    b.rowguid,
    c.generation,
    sys.fn_MSgeneration_downloadonly
    (
        c.generation,
        c.tablenick
    )
FROM #belong b
LEFT OUTER JOIN dbo.MSmerge_contents c ON 
    c.tablenick = b.tablenick
    AND c.rowguid = b.rowguid;

Орієнтовний план запитів включає інформацію про 3 запити:

  1. Запит вище
  2. Виклик функції fn_MSgeneration_downloadonly
  3. Виклик функції до властивості fn_MSArticle_has_downloadonly_property

Фактичний план запитів включає лише таку інформацію:

  1. Запит вище

Нічого про функції. Чому інформація про функції відсутня у фактичному плані?

Я спробував такі варіанти:

SET STATISTICS PROFILE ON
SET STATISTICS XML ON

Який створив фактичний план, але в ньому бракували частини 2 та 3 такі самі, як і коли я використовував параметр дійсного плану запитів у студії управління.

Якби, наприклад, я мав використовувати Profiler для збору інформації про виклики функції, які події я б обрав?


Не знайшов відповіді, спеціально пов’язаної з планами запитів, але я профілював SP: StmtStarting та SP: StmtCompleted, і він показав виклики функцій.

Відповіді:


17

І нічого про функції. Чому інформація про функції відсутня у фактичному плані?

Це з дизайну, з міркувань продуктивності.

Функції, що містять BEGINі ENDу визначенні створюють новий кадр стека T-SQL для кожного вхідного рядка. Іншим способом, функціональне тіло виконується окремо для кожного вхідного рядка . Цей єдиний факт пояснює більшість проблем продуктивності, пов’язаних зі скалярними функціями T-SQL та функціями з декількома операторами (зауважте, що функції в рядковій таблиці, що оцінюються, не використовують BEGIN...ENDсинтаксис).

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

Приклад

Розглянемо скалярну функцію T-SQL нижче, створену у зразковій базі даних AdventureWorks , яка повертає назву продукту з урахуванням його ідентифікатора:

CREATE FUNCTION dbo.DumbNameLookup
(
    @ProductID integer
)
RETURNS dbo.Name
AS
BEGIN
    RETURN
    (
        SELECT
            p.Name
        FROM Production.Product AS p
        WHERE
            p.ProductID = @ProductID
    );
END;

План попереднього виконання

План попереднього виконання (орієнтовний план у SSMS) показує інформацію плану для батьківського оператора та вкладених викликів функції:

-- Pre-execution plan shows main query and nested function call
SET SHOWPLAN_XML ON;
GO
SELECT dbo.DumbNameLookup(1);
GO
SET SHOWPLAN_XML OFF;

Вихід SSMS:

План попереднього виконання SSMS

Той самий XML, який розглядається в SQL Sentry Plan Explorer, чіткіше показує вкладений характер викликів:

План попереднього виконання ПП

Вихід після виконання

SSMS показує деталі лише для головного запиту, коли запитується вихід після виконання плану:

-- Post-execution plan shows main query only
SET STATISTICS XML ON;
SELECT dbo.DumbNameLookup(1);
SET STATISTICS XML OFF;

Після виконання SSMS

Ефект від продуктивності в іншому випадку може бути показаний за допомогою класу подій Showplan XML Statistics Profile в SQL Server Profiler, використовуючи запит, який викликає функцію кілька разів (один раз на рядок введення):

SELECT TOP (5)
    p.ProductID,
    dbo.DumbNameLookup(p.ProductID)
FROM Production.Product AS p;

Вихід профіля:

Виведення сліду

Існує п'ять окремих планів після виконання для виконання функцій та один для батьківського запиту. П’ять функціональних планів виглядають так на нижній панелі профілю:

Функціональні плани

План батьківського запиту:

Батьківський план

Виконання запиту без TOP (5)пункту призводить до повного плану виконання для кожного з 504 рядків у таблиці Product. Ви, напевно, можете побачити, як це швидко вийде з рук з більшими таблицями.

Ситуація для спускових механізмів зворотна. Вони не показують будь-якої інформації про план перед виконанням, але включають план після виконання. Це відображає заданий характер тригерів; кожен запускається один раз для всіх порушених рядків, а не один раз у ряд.


@PaulWhite Чи є якась вагома причина, що тригерні плани не відображаються при запиті прогнозованого плану виконання? Це здається корисною відсутністю функції. Я можу створити для нього елемент підключення.
usr

@usr - Може тому, що обраний фактичний кешований план може змінюватись залежно від фактичної кількості рядків, як описано тут? technet.microsoft.com/en-us/library/…
Мартін Сміт

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

@usr - Цей тут ? 3 місяці? Це повинен бути рекордний поворот для нового запиту на функції!
Мартін Сміт

@MartinSmith так, це. Це було "зафіксовано" 1-2 тому. Я дуже сподіваюся, що мені не доведеться запитувати магазин запитів. Я сподівався натиснути кнопку в SSMS. Власне, я був здивований, побачивши будь-яку зміну частини двигуна, яку не торкалися роками. Але, можливо, такого не було.
usr
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.