SQL Server có lưu trữ kết quả của hàm đa giá trị bảng không?


Câu trả lời:


23

Các kết quả của hàm có nhiều giá trị bảng (msTVF) không bao giờ được lưu trữ hoặc sử dụng lại trên các câu lệnh (hoặc kết nối), nhưng có một số cách mà kết quả msTVF có thể được sử dụng lại trong cùng một câu lệnh. Ở mức độ đó, một msTVF không nhất thiết phải được lặp lại mỗi lần nó được gọi.

Ví dụ msTVF

MsTVF (cố ý không hiệu quả) này trả về một phạm vi số nguyên đã chỉ định, với dấu thời gian trên mỗi hàng:

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;

Biến bảng tĩnh

Nếu tất cả các tham số cho lệnh gọi hàm là hằng số (hoặc hằng thời gian chạy), kế hoạch thực hiện sẽ đưa vào kết quả biến bảng một lần. Phần còn lại của kế hoạch có thể truy cập vào biến bảng nhiều lần. Bản chất tĩnh của biến bảng có thể được nhận ra từ kế hoạch thực hiện. Ví dụ:

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

Trả về một kết quả tương tự như:

Kết quả đơn giản

Kế hoạch thực hiện là:

Kế hoạch thực hiện đơn giản

Toán tử Sequence trước tiên gọi toán tử Hàm có giá trị bảng, điền vào biến bảng (lưu ý toán tử này không trả về hàng nào). Tiếp theo, Chuỗi gọi đầu vào thứ hai của nó, trả về nội dung của biến bảng (sử dụng Quét chỉ mục cụm trong trường hợp này).

Giveaway mà gói đang sử dụng kết quả biến bảng 'tĩnh' là toán tử Hàm có giá trị bảng bên dưới Trình tự - biến bảng cần được điền đầy đủ một lần trước khi phần còn lại của gói có thể đi.

Nhiều lượt truy cập

Để hiển thị kết quả biến bảng được truy cập nhiều lần, chúng tôi sẽ sử dụng bảng thứ hai với các hàng được đánh số từ 1 đến 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);

Và một truy vấn mới tham gia bảng này vào chức năng của chúng tôi (điều này cũng có thể được viết dưới dạng 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;

Kết quả là:

Tham gia kết quả

Kế hoạch thực hiện:

Tham gia kế hoạch

Như trước, Sequence đưa ra kết quả msTVF biến bảng đầu tiên. Tiếp theo, các vòng lặp lồng nhau được sử dụng để nối từng hàng từ bảng này Tsang một hàng khác từ kết quả msTVF. Do định nghĩa hàm bao gồm một chỉ mục hữu ích trên biến bảng, nên có thể sử dụng tìm kiếm chỉ mục.

Điểm mấu chốt là khi các tham số cho msTVF là các hằng số (bao gồm các biến & tham số) hoặc được coi là hằng số thời gian chạy cho câu lệnh của công cụ thực thi, kế hoạch sẽ có hai toán tử riêng biệt cho kết quả biến bảng msTVF: một để đưa vào bàn; một cách khác để truy cập kết quả, có thể truy cập bảng nhiều lần và có thể sử dụng các chỉ mục được khai báo trong định nghĩa hàm.

Các tham số tương quan và các tham số không cố định

Để làm nổi bật sự khác biệt khi các tham số tương quan (tham chiếu ngoài) hoặc tham số hàm không cố định được sử dụng, chúng tôi sẽ thay đổi nội dung của bảng Tđể hàm có nhiều việc phải làm hơn:

TRUNCATE TABLE dbo.T;

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

Truy vấn được sửa đổi sau đây hiện sử dụng tham chiếu ngoài tới bảng Ttrong một trong các tham số hàm:

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;

Truy vấn này mất khoảng 8 giây để trả về kết quả như sau:

Kết quả tương quan

Lưu ý sự khác biệt thời gian giữa các hàng trong cột ts. Các WHEREđiều khoản hạn chế kết quả cuối cùng cho một đầu ra hợp lý có kích thước, nhưng chức năng không hiệu quả vẫn còn mất một thời gian để cư biến bảng với 50.000-lẻ hàng (tùy thuộc vào giá trị tương quan của itừ bảng T).

Kế hoạch thực hiện là:

Kế hoạch thực hiện tương quan

Lưu ý thiếu một toán tử Sequence. Bây giờ, có một toán tử Hàm có giá trị bảng duy nhất điền vào biến bảng và trả về các hàng của nó trên mỗi lần lặp của các vòng lặp lồng nhau tham gia.

Để rõ ràng: chỉ với 5 hàng trong bảng T, toán tử Hàm có giá trị bảng chạy 5 lần. Nó tạo ra 50.001 hàng trên lần lặp đầu tiên, 50.002 trên lần thứ hai ... và cứ thế. Biến bảng là 'vứt đi' (cắt ngắn) giữa các lần lặp, do đó, mỗi trong số năm cuộc gọi là một dân số đầy đủ. Đây là lý do tại sao nó rất chậm và mỗi hàng mất khoảng thời gian để xuất hiện trong kết quả.

Ghi chú bên:

Đương nhiên, kịch bản ở trên được cố tình đưa ra để cho thấy hiệu suất có thể kém như thế nào khi msTVF cư trú nhiều hàng trên mỗi lần lặp.

Việc triển khai hợp lý mã trên sẽ đặt cả tham số msTVF thành ivà loại bỏ WHEREmệnh đề dự phòng . Biến bảng vẫn sẽ được cắt bớt và lặp lại trên mỗi lần lặp, nhưng chỉ với một hàng mỗi lần.

Chúng tôi cũng có thể tìm nạp các igiá trị tối thiểu và tối đa từ Tvà lưu trữ chúng trong các biến trong bước trước. Gọi hàm bằng các biến thay vì tham số tương quan sẽ cho phép sử dụng mẫu biến bảng 'tĩnh' như đã lưu ý trước đó.

Bộ nhớ đệm cho các tham số tương quan không thay đổi

Quay trở lại để giải quyết câu hỏi ban đầu một lần nữa, trong đó mẫu tĩnh Sequence không thể được sử dụng, SQL Server có thể tránh cắt ngắn và lặp lại biến bảng msTVF nếu không có tham số tương quan nào thay đổi kể từ lần lặp trước của phép nối vòng lặp lồng nhau.

Để chứng minh điều này, chúng tôi sẽ thay thế nội dung Tbằng năm giá trị giống nhau i :

TRUNCATE TABLE dbo.T;

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

Truy vấn với một tham số tương quan một lần nữa:

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;

Lần này kết quả xuất hiện trong khoảng 1,5 giây :

Kết quả hàng giống hệt nhau

Lưu ý các dấu thời gian giống hệt nhau trên mỗi hàng. Kết quả được lưu trong bộ đệm trong biến bảng được sử dụng lại cho các lần lặp tiếp theo trong đó giá trị tương quan ikhông thay đổi. Sử dụng lại kết quả nhanh hơn nhiều so với việc chèn 50.005 hàng mỗi lần.

Kế hoạch thực hiện trông rất giống với trước đây:

Lập kế hoạch cho các hàng giống hệt nhau

Sự khác biệt chính là ở Rebinds thực tếtua lại thực tế tính chất của Bảng Quý điều hành Chức năng:

Thuộc tính toán tử

Khi các tham số tương quan không thay đổi, SQL Server có thể phát lại (tua lại) các kết quả hiện tại trong biến bảng. Khi tương quan thay đổi, SQL Server phải cắt bớt và lặp lại biến bảng (rebind). Một rebind xảy ra ở lần lặp đầu tiên; bốn lần lặp lại tiếp theo đều là tua lại vì giá trị của T.ikhông đổi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.