ใช่.
ความล้มเหลวในการระบุWITH SCHEMABINDING
หมายความว่า SQL Server ข้ามการตรวจสอบรายละเอียดตามปกติที่ทำกับเนื้อหาของฟังก์ชัน มันทำเครื่องหมายฟังก์ชั่นเป็นการเข้าถึงข้อมูล (ตามที่กล่าวไว้ในลิงก์ที่ให้ไว้ในคำถาม)
นี่คือการเพิ่มประสิทธิภาพการปฏิบัติงาน ถ้ามันไม่ได้ทำให้สมมติฐานนี้ SQL Server จะต้องดำเนินการตรวจสอบรายละเอียดในทุกการเรียกใช้ฟังก์ชั่น (เนื่องจากฟังก์ชั่น unbound สามารถเปลี่ยนแปลงได้ตลอดเวลา)
มีคุณสมบัติฟังก์ชันที่สำคัญห้าประการ:
- ชะตา
- ความแม่นยำ
- การเข้าถึงข้อมูล
- การเข้าถึงข้อมูลระบบ
- การตรวจสอบระบบ
ตัวอย่างเช่นใช้ฟังก์ชัน scalar unbound ต่อไปนี้:
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);
คุณสมบัติการเข้าถึงข้อมูลสองได้รับการตั้งค่าความจริงและอีกสามจะถูกตั้งค่าเป็นเท็จ
สิ่งนี้มีความหมายเกินกว่าที่คาดการณ์ไว้ (ตัวอย่างเช่นใช้ในมุมมองที่จัดทำดัชนีหรือคอลัมน์ที่คำนวณได้ดัชนี)
ผลต่อตัวเพิ่มประสิทธิภาพข้อความค้นหา
determinismคุณสมบัติโดยเฉพาะอย่างยิ่งมีผลต่อการเพิ่มประสิทธิภาพการค้นหา มันมีกฎอย่างละเอียดเกี่ยวกับประเภทของการเขียนซ้ำและการจัดการที่อนุญาตให้ดำเนินการและสิ่งเหล่านี้ถูกจำกัด อย่างมากสำหรับองค์ประกอบที่ไม่ได้กำหนดไว้ ผลข้างเคียงนั้นค่อนข้างบอบบาง
ตัวอย่างเช่นพิจารณาสองตารางต่อไปนี้:
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
คำใบ้ (และความพยายามที่คล้ายกันอื่น ๆ ) จะไม่ประสบความสำเร็จ:
ปัญหาพื้นฐานคือเพิ่มประสิทธิภาพการค้นหาไม่สามารถเรียงลำดับองค์ประกอบแบบสอบถาม nondeterministic เป็นได้อย่างอิสระ
ในการสร้างการค้นหากริยาตัวกรองจะต้องถูกย้ายลงแผนไปที่การเข้าถึงข้อมูล T2 การเคลื่อนไหวนี้จะถูกป้องกันเมื่อฟังก์ชั่นไม่ได้กำหนดไว้
แก้ไขปัญหา
การแก้ไขสำหรับตัวอย่างนี้เกี่ยวข้องกับสองขั้นตอน:
- เพิ่ม
WITH SCHEMABINDING
- ทำให้ฟังก์ชั่นกำหนดขึ้น
ขั้นตอนแรกนั้นไม่สำคัญ ประการที่สองเกี่ยวข้องกับการลบ cast-impl implicit non-deterministic จาก string เป็น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;
คำจำกัดความของฟังก์ชันนี้สร้างแผนการสแกนและคุณสมบัติแสดงให้เห็นว่ามันยังไม่สามารถกำหนดได้: