Evet.
Belirtmek için başarısız WITH SCHEMABINDING
SQL Server normalde fonksiyon gövdesi üzerinde kılan ayrıntılı kontroller atladığı anlamına gelir. Bu sadece fonksiyona veri erişimi olarak işaretler (soruda verilen bağlantıda belirtildiği gibi).
Bu bir performans optimizasyonu. Bu varsayımı yapmazsa, SQL Server her işlev çağrısı için ayrıntılı denetimler yapmak zorunda kalırdı (unbound işlevi herhangi bir zamanda değişebileceğinden).
Orada beş önemli fonksiyon özellikleri:
- determinizm
- Hassas
- Veri erişimi
- Sistem Veri Erişimi
- Sistem Doğrulama
Örneğin, aşağıdaki sınırsız skaler fonksiyonunu kullanın:
CREATE FUNCTION dbo.F
(
@i integer
)
RETURNS datetime
AS
BEGIN
RETURN '19000101';
END;
Bir meta veri işlevi kullanarak beş özelliğe bakabiliriz:
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);
İki veri erişim özelliği doğru olarak ayarlandı ve diğer üç değer yanlış olarak ayarlandı .
Bunun beklenebileceklerin ötesinde etkileri vardır (örneğin, indekslenmiş görünümlerde veya indekslenmiş hesaplanmış sütunlarda kullanın).
Sorgu iyileştirici üzerindeki etkiler
Özellikle Determinism özelliği, sorgu en iyi duruma getiricisi etkiler. Yapılmasına izin verilen yeniden yazma ve manipülasyon türleriyle ilgili ayrıntılı kuralları vardır ve bunlar deterministik olmayan öğeler için çok kısıtlıdır . Yan etkiler oldukça ince olabilir.
Örneğin, aşağıdaki iki tabloyu göz önünde bulundurun:
CREATE TABLE dbo.T1
(
SomeInteger integer PRIMARY KEY
);
GO
CREATE TABLE dbo.T2
(
SomeDate datetime PRIMARY KEY
);
... ve (daha önce tanımlandığı gibi) işlevini kullanan bir sorgu:
SELECT *
FROM dbo.T1 AS T1
JOIN dbo.T2 AS T2
ON T2.SomeDate = dbo.F(T1.SomeInteger);
Sorgu planı beklendiği gibi, T2 tablosunda bir araya getirme özelliğini içeriyor:
Bununla birlikte, aynı mantıksal sorgu türetilmiş bir tablo veya ortak tablo ifadesi kullanılarak yazılmışsa:
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;
Yürütme planı şimdi, bir süzgecin içinde sıkışmış işlevi içeren yüklemi içeren bir tarama özelliğine sahip:
Bu, türetilmiş tablo veya genel tablo ifadesinin bir görünüm veya satır içi işlevi ile değiştirilmesi durumunda da olur. Bir FORCESEEK
ipucu (ve benzeri diğer girişimler) başarılı olmaz:
Temel sorun, sorgu iyileştiricinin teknik olmayan sorgu öğelerini serbestçe yeniden sıralayamamasıdır .
Bir arama yapmak için, Filtre yükleminin plandan T2 veri erişimine taşınması gerekir. Bu hareket, fonksiyon deterministik olmadığı zaman önlenir.
düzeltmek
Bu örnek için düzeltme iki adımı içerir:
- Eklemek
WITH SCHEMABINDING
- Fonksiyonu deterministik yap
İlk adım önemsizdir. İkincisi, deterministik olmayan örtük alçı dizeden datetime
; bir deterministic ile değiştirerek CONVERT
. Hiçbiri kendi başına yeterli değil .
ALTER FUNCTION dbo.F
(
@i integer
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
-- Convert with a deterministic style
RETURN CONVERT(datetime, '19000101', 112);
END;
İşlev özellikleri şimdi:
İyileştirici serbest bırakıldığında, tüm örnekler şimdi istenen arama planını oluşturur .
İşlevde a CAST
ile kullanılmasının datetime
işe yaramayacağını unutmayın, çünkü bu sözdiziminde bir dönüştürme stili belirtmek mümkün değildir:
ALTER FUNCTION dbo.F
(
@i integer
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
-- Convert with a deterministic style
RETURN CAST('19000101' AS datetime);
END;
Bu işlev tanımı, tarama planını oluşturur ve özellikleri, belirleyici olmadığını gösterir: