CTE ที่ไม่ได้ใช้งานในคิวรีส่งผลต่อประสิทธิภาพและ / หรือเปลี่ยนแผนคิวรีที่สร้างขึ้นหรือไม่
CTE ที่ไม่ได้ใช้งานในคิวรีส่งผลต่อประสิทธิภาพและ / หรือเปลี่ยนแผนคิวรีที่สร้างขึ้นหรือไม่
คำตอบ:
ไม่ปรากฏว่าพวกเขาทำ แต่สิ่งนี้ใช้ได้กับ CTE ที่ซ้อนกันเท่านั้น
สร้างตารางชั่วคราวสองตาราง:
CREATE TABLE #t1 (id INT);
INSERT #t1 ( id )
VALUES ( 1 );
CREATE TABLE #t2 (id INT);
INSERT #t2 ( id )
VALUES ( 1 );
แบบสอบถาม 1:
WITH your_mom AS (
SELECT TOP 1 *
FROM #t1 AS t
),
also_your_mom AS (
SELECT TOP 1 *
FROM #t2 AS t
)
SELECT *
FROM your_mom;
แบบสอบถาม 2:
WITH your_mom AS (
SELECT TOP 1 *
FROM #t1 AS t
),
also_your_mom AS (
SELECT TOP 1 *
FROM #t2 AS t
)
SELECT *
FROM also_your_mom;
แผนการค้นหา:
มีค่าใช้จ่าย แต่ส่วนที่ไม่จำเป็นของแบบสอบถามถูกกำจัดเร็วมาก (ในระหว่างการแยกวิเคราะห์ในกรณีนี้ขั้นตอนการทำให้เข้าใจง่ายในกรณีที่ซับซ้อนมากขึ้น) ดังนั้นการทำงานเพิ่มเติมจึงน้อยมากอย่างแท้จริงและไม่ได้มีส่วนทำให้เกิดต้นทุน การเพิ่มประสิทธิภาพ
+1 ใน Erik แต่ต้องการเพิ่มสองสิ่ง (ซึ่งทำงานได้ไม่ดีในความคิดเห็น):
คุณไม่จำเป็นต้องดูที่แผนปฏิบัติการเพื่อดูว่ามันถูกเพิกเฉยเมื่อไม่ได้ใช้งาน ต่อไปนี้ควรสร้างข้อผิดพลาด "หารด้วย 0" แต่ไม่ได้เนื่องจากcte2
ไม่ได้ถูกเลือกจากเลย:
;WITH cte1 AS
(
SELECT 1 AS [Bob]
),
cte2 AS (
SELECT 1 / 0 AS [Err]
FROM cte1
)
SELECT *
FROM cte1;
สามารถละเว้น CTE แม้ว่าจะเป็น CTE เดียวเท่านั้นและแม้ว่าจะถูกเลือกจากหากมีเหตุผลทุกแถวจะถูกยกเว้น ต่อไปนี้เป็นกรณีที่เคียวรีเครื่องมือเพิ่มประสิทธิภาพทราบล่วงหน้าว่าจะไม่มีแถวใดสามารถส่งคืนจาก CTE ได้ดังนั้นจึงไม่ต้องกังวลที่จะเรียกใช้งาน:
;WITH cte AS
(
SELECT 1 / 0 AS [Bob]
)
SELECT TOP (1) [object_id]
FROM sys.objects
UNION ALL
SELECT cte.[Bob]
FROM cte
WHERE 1 = 0;
เกี่ยวกับประสิทธิภาพ CTE ที่ไม่ได้ใช้จะถูกวิเคราะห์และเรียบเรียง (หรือรวบรวมอย่างน้อยในกรณีด้านล่าง) ดังนั้นจึงไม่ได้ถูกเพิกเฉย 100% แต่ค่าใช้จ่ายจะต้องไม่สำคัญและไม่คุ้มค่าที่จะกังวล
เมื่อแยกวิเคราะห์เท่านั้นไม่มีข้อผิดพลาด:
SET PARSEONLY ON;
;WITH cte1 AS
(
SELECT obj.[NotHere]
FROM sys.objects obj
)
SELECT TOP (1) so.[name]
FROM sys.objects so
GO
SET PARSEONLY OFF;
GO
เมื่อทำทุกสิ่งที่ขาดการปฏิบัติก็มีปัญหา:
GO
SET NOEXEC ON;
GO
;WITH cte1 AS
(
SELECT obj.[NotHere]
FROM sys.objects obj
)
SELECT TOP (1) so.[name]
FROM sys.objects so
GO
SET NOEXEC OFF;
GO
/*
Msg 207, Level 16, State 1, Line XXXXX
Invalid column name 'NotHere'.
*/
NEWID()
มุมมองเพื่อใช้ใน UDF สามารถส่งคืนค่าเดียวกันจากการโทรหลายครั้งเนื่องจากเครื่องมือเพิ่มประสิทธิภาพการแคช