Iya.
Gagal menentukan WITH SCHEMABINDING
berarti SQL Server melewatkan pemeriksaan terperinci yang biasanya dilakukan pada fungsi tubuh. Ini hanya menandai fungsi sebagai mengakses data (seperti yang disebutkan dalam tautan yang diberikan dalam pertanyaan).
Ini adalah pengoptimalan kinerja. Jika tidak membuat asumsi ini, SQL Server harus melakukan pemeriksaan terperinci pada setiap pemanggilan fungsi (karena fungsi tidak terikat dapat berubah kapan saja).
Ada lima properti fungsi penting:
- Determinisme
- Presisi
- Akses data
- Akses Data Sistem
- Verifikasi Sistem
Misalnya, ambil fungsi skalar tidak terikat berikut:
CREATE FUNCTION dbo.F
(
@i integer
)
RETURNS datetime
AS
BEGIN
RETURN '19000101';
END;
Kita bisa melihat lima properti menggunakan fungsi metadata:
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);
Dua properti akses data telah diset true, dan tiga lainnya diset false .
Ini memiliki implikasi di luar yang mungkin diharapkan (misalnya, digunakan dalam tampilan yang diindeks atau kolom yang dihitung dengan indeks).
Efek pada pengoptimal kueri
The Determinisme properti khususnya mempengaruhi query optimizer. Ini memiliki aturan rinci tentang jenis penulisan ulang dan manipulasi yang diizinkan untuk dilakukan, dan ini sangat terbatas untuk elemen non-deterministik. Efek sampingnya bisa sangat halus.
Misalnya, perhatikan dua tabel berikut:
CREATE TABLE dbo.T1
(
SomeInteger integer PRIMARY KEY
);
GO
CREATE TABLE dbo.T2
(
SomeDate datetime PRIMARY KEY
);
... dan kueri yang menggunakan fungsi (seperti yang didefinisikan sebelumnya):
SELECT *
FROM dbo.T1 AS T1
JOIN dbo.T2 AS T2
ON T2.SomeDate = dbo.F(T1.SomeInteger);
Rencana kueri seperti yang diharapkan, menampilkan tabel seek T2:
Namun, jika kueri logis yang sama ditulis menggunakan tabel turunan atau ekspresi tabel umum:
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;
Paket eksekusi sekarang menampilkan pemindaian, dengan predikat yang melibatkan fungsi tersangkut dalam Filter:
Ini juga terjadi jika tabel yang diturunkan atau ekspresi tabel umum digantikan oleh fungsi tampilan atau in-line. Sebuah FORCESEEK
petunjuk (dan upaya lain yang serupa) tidak akan berhasil:
Masalah mendasar adalah bahwa pengoptimal kueri tidak dapat menyusun ulang elemen permintaan nondeterministic secara bebas .
Untuk menghasilkan pencarian, predikat Filter perlu dipindahkan ke paket akses T2. Gerakan ini dicegah ketika fungsinya non-deterministik.
Memperbaiki
Perbaikan untuk contoh ini melibatkan dua langkah:
- Menambahkan
WITH SCHEMABINDING
- Buat fungsi deterministik
Langkah pertama adalah sepele. Yang kedua melibatkan menghilangkan cast implisit non-deterministik dari string ke datetime
; menggantinya dengan deterministik CONVERT
. Tidak cukup dengan sendirinya .
ALTER FUNCTION dbo.F
(
@i integer
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
-- Convert with a deterministic style
RETURN CONVERT(datetime, '19000101', 112);
END;
Properti fungsi sekarang:
Dengan pengoptimal yang dibebaskan, semua contoh sekarang menghasilkan rencana pencarian yang diinginkan .
Perhatikan bahwa menggunakan CAST
to datetime
dalam fungsi tidak akan berfungsi, karena tidak mungkin menentukan gaya konversi di sintaks itu:
ALTER FUNCTION dbo.F
(
@i integer
)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
-- Convert with a deterministic style
RETURN CAST('19000101' AS datetime);
END;
Definisi fungsi ini menghasilkan rencana pemindaian, dan properti menunjukkannya tetap non-deterministik: