SQL Server แคชผลลัพธ์ของฟังก์ชันหลายค่าในตารางหรือไม่?


22

ฟังก์ชั่นมูลค่าตารางหลายงบส่งกลับผลลัพธ์ในตัวแปรตาราง

ผลลัพธ์เหล่านี้เคยถูกนำมาใช้ซ้ำหรือฟังก์ชั่นจะถูกประเมินอย่างเต็มที่ทุกครั้งที่มีการเรียกใช้หรือไม่

คำตอบ:


23

ผลลัพธ์ของฟังก์ชั่นมูลค่าตารางหลายคำสั่ง (msTVF) จะไม่ถูกแคชหรือนำกลับมาใช้ซ้ำระหว่างคำสั่ง (หรือการเชื่อมต่อ) แต่มีสองวิธีที่ผลลัพธ์ msTVF อาจนำกลับมาใช้ใหม่ในคำสั่งเดียวกัน ในขอบเขตนั้น msTVF ไม่จำเป็นต้องมีการเติมคำซ้ำในแต่ละครั้งที่มีการเรียก

ตัวอย่าง msTVF

msTVF นี้ (ไม่มีประสิทธิภาพโดยเจตนา) ส่งคืนช่วงจำนวนเต็มตามที่ระบุโดยมีการประทับเวลาในแต่ละแถว:

IF OBJECT_ID(N'dbo.IntegerRange', 'TF') IS NOT NULL
    DROP FUNCTION dbo.IntegerRange;
GO
CREATE FUNCTION dbo.IntegerRange (@From integer, @To integer)
RETURNS @T table 
(
    n integer PRIMARY KEY, 
    ts datetime DEFAULT CURRENT_TIMESTAMP
)
WITH SCHEMABINDING
AS
BEGIN
    WHILE @From <= @To
    BEGIN
        INSERT @T (n)
        VALUES (@From);

        SET @From = @From + 1;
    END;
    RETURN;
END;

ตัวแปรตารางแบบคงที่

หากพารามิเตอร์ทั้งหมดในการเรียกใช้ฟังก์ชันเป็นค่าคงที่ (หรือค่าคงที่รันไทม์) แผนการดำเนินการจะเติมผลลัพธ์ของตัวแปรตารางหนึ่งครั้ง ส่วนที่เหลือของแผนอาจเข้าถึงตัวแปรตารางหลายครั้ง ธรรมชาติของตัวแปรตารางสามารถรับรู้ได้จากแผนการดำเนินการ ตัวอย่างเช่น:

SELECT
    IR.n,
    IR.ts 
FROM dbo.IntegerRange(1, 5) AS IR
ORDER BY
    IR.n;

ส่งคืนผลลัพธ์ที่คล้ายกับ:

ผลลัพธ์ที่ง่าย

แผนการดำเนินการคือ:

แผนการดำเนินการอย่างง่าย

ตัวดำเนินการลำดับจะเรียกใช้ตัวดำเนินการฟังก์ชันที่ประเมินค่าในตารางก่อนซึ่งจะเติมตัวแปรตาราง (หมายเหตุตัวดำเนินการนี้จะไม่ส่งคืนแถว) ถัดไป Sequence เรียกอินพุตที่สองซึ่งส่งคืนเนื้อหาของตัวแปรตาราง (โดยใช้การสแกนดัชนีแบบคลัสเตอร์ในกรณีนี้)

ของกำนัลที่แผนกำลังใช้ผลลัพธ์ตารางตัวแปร 'คงที่' คือตัวดำเนินการฟังก์ชันที่ประเมินค่าตารางด้านล่างของลำดับ - ตัวแปรตารางจะต้องมีการเติมข้อมูลให้สมบูรณ์ก่อนที่ส่วนที่เหลือของแผนจะไปได้

การเข้าถึงหลาย

เพื่อแสดงผลลัพธ์ของตัวแปรตารางที่เข้าถึงได้มากกว่าหนึ่งครั้งเราจะใช้ตารางที่สองที่มีจำนวนแถวตั้งแต่ 1 ถึง 5:

IF OBJECT_ID(N'dbo.T', 'U') IS NOT NULL
    DROP TABLE dbo.T;

CREATE TABLE dbo.T (i integer NOT NULL);

INSERT dbo.T (i) 
VALUES (1), (2), (3), (4), (5);

และแบบสอบถามใหม่ที่เข้าร่วมในตารางนี้ในฟังก์ชันของเรา (ซึ่งสามารถเขียนเป็นAPPLY)

SELECT T.i,
       IR.n,
       IR.ts
FROM dbo.T AS T
JOIN dbo.IntegerRange(1, 5) AS IR
    ON IR.n = T.i;

ผลลัพธ์คือ:

เข้าร่วมผล

แผนการดำเนินการ:

เข้าร่วมแผน

ก่อนหน้านี้ Sequence จะเติมผลลัพธ์ของตัวแปรตาราง msTVF ก่อน ถัดไปจะใช้ลูปซ้อนกันเพื่อเข้าร่วมแต่ละแถวจากตารางTหนึ่งไปยังอีกแถวหนึ่งจากผลลัพธ์ msTVF เนื่องจากนิยามฟังก์ชันรวมดัชนีที่มีประโยชน์ไว้ในตัวแปรตารางจึงสามารถใช้การค้นหาดัชนีได้

ประเด็นสำคัญคือเมื่อพารามิเตอร์ของ msTVF เป็นค่าคงที่ (รวมถึงตัวแปร & พารามิเตอร์) หรือถือว่าเป็นค่าคงที่แบบรันไทม์สำหรับคำสั่งโดยโปรแกรมการดำเนินการแผนจะมีตัวดำเนินการแยกกันสองตัวสำหรับผลลัพธ์ตัวแปรตาราง msTVF: หนึ่งเพื่อเติม ตาราง; อีกรายการหนึ่งเพื่อเข้าถึงผลลัพธ์อาจเข้าถึงตารางหลายครั้งและอาจใช้ดัชนีที่ประกาศไว้ในนิยามฟังก์ชัน

พารามิเตอร์ที่สัมพันธ์กันและพารามิเตอร์ที่ไม่คงที่

เพื่อเน้นความแตกต่างเมื่อใช้พารามิเตอร์ที่มีความสัมพันธ์ (การอ้างอิงภายนอก) หรือการใช้ฟังก์ชั่นที่ไม่คงที่เราจะเปลี่ยนเนื้อหาของตารางTเพื่อให้ฟังก์ชั่นมีงานให้ทำมากมาย:

TRUNCATE TABLE dbo.T;

INSERT dbo.T (i) 
VALUES (50001), (50002), (50003), (50004), (50005);

แบบสอบถามที่แก้ไขแล้วต่อไปนี้ใช้การอ้างอิงภายนอกไปยังตารางTในหนึ่งในพารามิเตอร์ฟังก์ชัน:

SELECT T.i,
       IR.n,
       IR.ts
FROM dbo.T AS T
CROSS APPLY dbo.IntegerRange(1, T.i) AS IR
WHERE IR.n = T.i;

ข้อความค้นหานี้ใช้เวลาประมาณ8 วินาทีในการส่งคืนผลลัพธ์เช่น:

ผลลัพธ์ที่สัมพันธ์กัน

tsขอให้สังเกตความแตกต่างของเวลาระหว่างแถวในคอลัมน์ WHEREข้อ จำกัด ผลสุดท้ายสำหรับการส่งออกอย่างสมเหตุสมผลขนาด แต่ฟังก์ชั่นที่ไม่มีประสิทธิภาพยังคงใช้เวลาในขณะที่จะเติมตัวแปรตารางที่มี 50,000 แปลกแถว (ขึ้นอยู่กับค่าความสัมพันธ์ของiจากตารางT)

แผนการดำเนินการคือ:

แผนการดำเนินการที่เกี่ยวข้อง

สังเกตเห็นการขาดตัวดำเนินการลำดับ ขณะนี้มีตัวดำเนินการ Table Valued Function หนึ่งเดียวที่เติมตัวแปรตารางและส่งคืนแถวในแต่ละการวนซ้ำของการรวมลูปซ้อนกัน

เพื่อความชัดเจน: มีเพียง 5 แถวในตาราง T ตัวดำเนินการฟังก์ชันประเมินค่าตารางจะทำงาน 5 ครั้ง มันสร้างแถว 50,001 ในการทำซ้ำครั้งแรก 50,002 ในแถวที่สอง ... และอื่น ๆ ตัวแปรตารางคือ 'ถูกโยนทิ้ง' (ตัด) ระหว่างการวนซ้ำดังนั้นการเรียกห้าครั้งแต่ละครั้งจึงเป็นประชากรเต็มจำนวน นี่คือสาเหตุที่มันช้ามากและแต่ละแถวใช้เวลาประมาณเดียวกันในการปรากฏในผลลัพธ์

หมายเหตุด้านข้าง:

ตามปกติแล้วสถานการณ์ด้านบนมีเจตนาที่จะแสดงให้เห็นว่าประสิทธิภาพที่ไม่ดีสามารถเกิดขึ้นได้อย่างไรเมื่อ msTVF ส่งผลให้เกิดแถวจำนวนมากในการทำซ้ำแต่ละครั้ง

ที่เหมาะสมดำเนินการตามรหัสข้างต้นจะตั้งทั้งพารามิเตอร์ msTVF ไปiและลบซ้ำซ้อนWHEREข้อ ตัวแปรตารางจะยังคงถูกตัดทอนและ repopulated ในแต่ละการทำซ้ำ แต่มีเพียงหนึ่งแถวในแต่ละครั้ง

นอกจากนี้เรายังสามารถดึงค่าต่ำสุดและiค่าสูงสุดจากTและเก็บไว้ในตัวแปรในขั้นตอนก่อนหน้า การเรียกใช้ฟังก์ชันด้วยตัวแปรแทนพารามิเตอร์ที่มีความสัมพันธ์กันจะอนุญาตให้ใช้รูปแบบตัวแปรตาราง 'คงที่' ได้ตามที่ระบุไว้ก่อนหน้านี้

การแคชสำหรับพารามิเตอร์ที่มีความสัมพันธ์ไม่เปลี่ยนแปลง

กลับไปยังที่อยู่ของคำถามเดิมอีกครั้งโดยที่ไม่สามารถใช้รูปแบบสแตติกของ Sequence ได้ SQL Server สามารถหลีกเลี่ยงการตัดทอนและปรับเปลี่ยนตัวแปรตาราง msTVF หากไม่มีพารามิเตอร์ที่สัมพันธ์กันเปลี่ยนไปนับตั้งแต่การวนซ้ำก่อนหน้า

เพื่อสาธิตสิ่งนี้เราจะแทนที่เนื้อหาTด้วยค่าที่เหมือนกัน ห้าiค่า:

TRUNCATE TABLE dbo.T;

INSERT dbo.T (i) 
VALUES (50005), (50005), (50005), (50005), (50005);

แบบสอบถามที่มีพารามิเตอร์ที่เกี่ยวข้องอีกครั้ง:

SELECT T.i,
       IR.n,
       IR.ts
FROM dbo.T AS T
CROSS APPLY dbo.IntegerRange(1, T.i) AS IR
WHERE IR.n = T.i;

เวลานี้ผลลัพธ์ปรากฏในประมาณ1.5 วินาที :

ผลลัพธ์แถวที่เหมือนกัน

บันทึกการประทับเวลาที่เหมือนกันในแต่ละแถว ผลลัพธ์ที่แคชในตัวแปรตารางจะถูกใช้ซ้ำสำหรับการทำซ้ำในภายหลังโดยที่ค่าที่สัมพันธ์กันiจะไม่เปลี่ยนแปลง การใช้ผลลัพธ์ซ้ำเร็วกว่าการแทรก 50,005 แถวในแต่ละครั้ง

แผนการดำเนินการมีลักษณะคล้ายกับก่อนหน้านี้มาก:

วางแผนสำหรับแถวที่เหมือนกัน

ความแตกต่างที่สำคัญอยู่ในคุณสมบัติการตอบกลับจริงและการกรอกลับจริงของตัวดำเนินการฟังก์ชันที่คิดมูลค่าตาราง:

คุณสมบัติผู้ประกอบการ

เมื่อพารามิเตอร์ที่สัมพันธ์กันไม่เปลี่ยนแปลง SQL Server สามารถเล่นซ้ำ (ย้อนกลับ) ผลลัพธ์ปัจจุบันในตัวแปรตาราง เมื่อการเปลี่ยนแปลงที่เกี่ยวข้อง SQL Server ต้องตัดทอนและ repopulate ตัวแปรตาราง (rebind) หนึ่ง rebind เกิดขึ้นในการทำซ้ำครั้งแรก; การวนซ้ำที่ตามมาสี่ครั้งจะย้อนกลับทั้งหมดเนื่องจากค่าของT.iไม่เปลี่ยนแปลง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.