回答:
はい。
指定に失敗するWITH SCHEMABINDING
と、SQL Serverは関数本体に対して通常行う詳細なチェックをスキップします。関数にデータへのアクセスとしてマークするだけです(質問のリンクに記載されています)。
これはパフォーマンスの最適化です。この仮定を行わなかった場合、SQL Serverはすべての関数呼び出しで詳細なチェックを実行する必要があります(非バインド関数はいつでも変更される可能性があるため)。
5つの重要な関数プロパティがあります。
たとえば、次の非バインドスカラー関数を使用します。
CREATE FUNCTION dbo.F
(
@i integer
)
RETURNS datetime
AS
BEGIN
RETURN '19000101';
END;
メタデータ関数を使用して5つのプロパティを確認できます。
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);
2つのデータアクセスプロパティはtrueに設定され、他の3つのプロパティはfalseに設定されています。
これには、予想されるもの以外の意味があります(たとえば、インデックス付きビューまたはインデックス付き計算列での使用)。
決定論の特にプロパティは、クエリオプティマイザに影響を与えます。実行が許可されている書き換えと操作の種類に関する詳細なルールがあり、これらは非決定的要素に対して非常に制限されています。副作用は非常に微妙な場合があります。
たとえば、次の2つのテーブルを考えます。
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データアクセスに移動する必要があります。関数が非決定的である場合、この移動は防止されます。
この例の修正には、2つのステップが含まれます。
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
to を使用しdatetime
ても機能しないことに注意してください。その構文では変換スタイルを指定できないためです。
ALTER FUNCTION dbo.F
(
@i integer
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
-- Convert with a deterministic style
RETURN CAST('19000101' AS datetime);
END;
この関数定義はスキャンプランを生成し、プロパティは非決定性のままであることを示しています。