Чи є якась користь від того, щоб ЗАБЕЗПЕЧИТИ функцію поза захистом від Хелловіна?


52

Загальновідомо, що SCHEMABINDINGфункція може уникнути зайвої котушки в планах оновлення:

Якщо ви використовуєте прості UDF з T-SQL, які не торкаються жодної таблиці (тобто не мають доступу до даних), переконайтеся, що ви вказали SCHEMABINDINGпараметр під час створення UDF. Це зробить схему UDFs і забезпечить, що оптимізатор запитів не генерує зайвих операторів котушки для планів запитів із залученням цих UDF.

Чи є інші переваги SCHEMABINDINGфункції, навіть якщо вона не має доступу до даних?

Відповіді:


78

Так.

Якщо не вказати WITH SCHEMABINDINGзасоби, SQL Server пропускає детальні перевірки, які він зазвичай робить на тілі функції. Він просто позначає функцію як доступ до даних (як зазначено у посиланні, наведеному у питанні).

Це оптимізація продуктивності. Якщо б цього не було зроблено, SQL Server повинен був би здійснити детальну перевірку кожного виклику функції (оскільки незв'язана функція може змінитися в будь-який час).

Існує п'ять важливих властивостей функції:

  • Детермінізм
  • Точність
  • Доступ до даних
  • Доступ до системних даних
  • Перевірка системи

Наприклад, візьміть таку незв'язану скалярну функцію:

CREATE FUNCTION dbo.F
(
    @i integer
)
RETURNS datetime
AS
BEGIN
    RETURN '19000101';
END;

Ми можемо розглянути п’ять властивостей за допомогою функції метаданих:

SELECT 
    IsDeterministic = OBJECTPROPERTYEX(Func.ID, 'IsDeterministic'),
    IsPrecise = OBJECTPROPERTYEX(Func.ID, 'IsPrecise'),
    IsSystemVerified = OBJECTPROPERTYEX(Func.ID, 'IsSystemVerified'),
    UserDataAccess = OBJECTPROPERTYEX(Func.ID, 'UserDataAccess'),
    SystemDataAccess = OBJECTPROPERTYEX(Func.ID, 'SystemDataAccess')
FROM (VALUES(OBJECT_ID(N'dbo.F', N'FN'))) AS Func (ID);

Результат

Дві властивості доступу до даних встановлені істинними, а інші три встановлені помилковими .

Це має наслідки, ніж ті, які можна очікувати (наприклад, використання в індексованих поданнях або індексованих обчислених стовпцях).

Вплив на оптимізатор запитів

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

Наприклад, розглянемо наступні дві таблиці:

CREATE TABLE dbo.T1
(
    SomeInteger integer PRIMARY KEY
);
GO
CREATE TABLE dbo.T2
(
    SomeDate datetime PRIMARY KEY
);

... і запит, який використовує функцію (як визначено раніше):

SELECT * 
FROM dbo.T1 AS T1
JOIN dbo.T2 AS T2
    ON T2.SomeDate = dbo.F(T1.SomeInteger);

План запитів, як очікується, містить запит на таблицю T2:

Шукайте план

Однак якщо той самий логічний запит записується за допомогою похідної таблиці або вираження загальної таблиці:

WITH CTE AS
(
    SELECT *, dt = dbo.F(T1.SomeInteger) 
    FROM dbo.T1 AS T1
)
SELECT * 
FROM CTE
JOIN dbo.T2 AS T2
    ON T2.SomeDate = CTE.dt;

-- Derived table
SELECT
    *
FROM 
(
    SELECT *, dt = dbo.F(T1.SomeInteger)
    FROM dbo.T1 AS T1
) AS T1
JOIN dbo.T2 AS T2
    ON T2.SomeDate = T1.dt;

План виконання тепер містить сканування, при цьому предикат включає функцію, застрягнуту у Фільтр:

План сканування

Це також відбувається, якщо виведене вираження таблиці або загальний табличний вираз замінено функцією перегляду або рядка. FORCESEEKНатяк (і інші подібні спроби) не вдасться:

Повідомлення про помилку

Основоположне питання полягає в тому, що оптимізатор запитів не може вільно змінювати недетерміновані елементи запиту .

Щоб здійснити пошук, предикат фільтра потрібно було б перемістити вниз по плану до доступу до даних T2. Цей рух запобігається, коли функція не є детермінованою.

Виправити

Виправлення цього прикладу включає два етапи:

  1. Додайте WITH SCHEMABINDING
  2. Зробіть функцію детермінованою

Перший крок - тривіальний. Другий включає вилучення недетермінованого неявного виступу з рядка до datetime; замінивши її детермінованою CONVERT. Жоден із них недостатній сам по собі .

ALTER FUNCTION dbo.F
(
    @i integer
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
    -- Convert with a deterministic style
    RETURN CONVERT(datetime, '19000101', 112);
END;

Властивості функції тепер:

Нові властивості

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


Зверніть увагу , що використання CASTдля datetimeв функції не буде працювати, тому що це не представляється можливим визначити стиль перетворення в цьому синтаксисі:

ALTER FUNCTION dbo.F
(
    @i integer
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
    -- Convert with a deterministic style
    RETURN CAST('19000101' AS datetime);
END;

Це визначення функції виробляє план сканування, і властивості показують, що він залишається недетермінованим:

Властивості функції CAST

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