Tại sao SQL Server phiên bản tính toán vô hướng khi tôi CHỌN một cột được tính toán bền vững?


21

Ba SELECTtuyên bố trong mã này

USE [tempdb];
GO

SET NOCOUNT ON;

CREATE TABLE dbo.persist_test (
      id            INT NOT NULL
    , id5           AS (id * 5)
    , id5p          AS (id * 5) PERSISTED
);

INSERT INTO dbo.persist_test (id)
VALUES (1), (2), (3);

SELECT id
FROM dbo.persist_test;

SELECT id5
FROM dbo.persist_test;

SELECT id5p
FROM dbo.persist_test;

DROP TABLE dbo.persist_test;

tạo kế hoạch này:

kế hoạch thực hiện

Tại sao cuối cùng SELECT, đang chọn một giá trị bền vững, tạo ra một toán tử vô hướng tính toán ?


3
Xem câu trả lời của @ SqlKiwi tại đây: Tại sao Kế hoạch thực hiện bao gồm lệnh gọi hàm do người dùng xác định cho một cột được tính vẫn tồn tại? . Trong truy vấn của bạn, danh sách cột đầu ra từ bảng chỉ [tempdb].[dbo].[persist_test].idvà nó tính toán giá trị mặc dù vẫn tồn tại.
Martin Smith

Câu trả lời:


14

Chỉ cần tóm tắt các kết quả thử nghiệm trong các ý kiến, đây dường như là một trường hợp cạnh xảy ra khi bạn có hai cột được tính toán trong cùng một bảng, một persistedvà một không tồn tại và cả hai đều có cùng định nghĩa.

Trong kế hoạch cho truy vấn

SELECT id5p
FROM dbo.persist_test;

Bảng quét trên persist_testchỉ phát ra idcột. Phép tính vô hướng tiếp theo nhân với 5 và xuất ra một cột được gọi id5mặc dù thực tế là cột này thậm chí không được tham chiếu trong truy vấn. Phép tính vô hướng cuối cùng cùng lấy giá trị id5và đầu ra dưới dạng cột được gọi id5p.

Sử dụng các cờ theo dõi được giải thích trong Trình tối ưu hóa truy vấn Deep Dive - Phần 2 (từ chối trách nhiệm: các cờ theo dõi này không có giấy tờ / không được hỗ trợ) và xem xét truy vấn

SELECT id5,
       id5p,
       ( id * 5 )
FROM   dbo.persist_test 
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8606);

Cung cấp đầu ra

Cây trước khi chuẩn hóa dự án

LogOp_Project

    LogOp_Get TBL: dbo.persist_test dbo.persist_test TableID=1717581157 TableReferenceID=0 IsRow: COL: IsBaseRow1002 

    AncOp_PrjList 

        AncOp_PrjEl QCOL: [tempdb].[dbo].[persist_test].id5

            ScaOp_Arithmetic x_aopMult

                ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id

                ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=5)

        AncOp_PrjEl QCOL: [tempdb].[dbo].[persist_test].id5p

            ScaOp_Arithmetic x_aopMult

                ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id

                ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=5)

        AncOp_PrjEl COL: Expr1004 

            ScaOp_Arithmetic x_aopMult

                ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id

                ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=5)

Cây sau khi bình thường hóa dự án

LogOp_Project

    LogOp_Get TBL: dbo.persist_test dbo.persist_test TableID=1717581157 TableReferenceID=0 IsRow: COL: IsBaseRow1002 

    AncOp_PrjList 

        AncOp_PrjEl QCOL: [tempdb].[dbo].[persist_test].id5

            ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id5

        AncOp_PrjEl QCOL: [tempdb].[dbo].[persist_test].id5p

            ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id5

        AncOp_PrjEl COL: Expr1004 

            ScaOp_Identifier QCOL: [tempdb].[dbo].[persist_test].id5

Vì vậy, có vẻ như tất cả các định nghĩa cột được tính toán được mở rộng ra sau đó trong giai đoạn Chuẩn hóa dự án, tất cả các biểu thức giống hệt nhau được khớp lại với các cột được tính toán và nó chỉ xảy ra khớp với id5trường hợp này. tức là nó không đưa ra bất kỳ ưu tiên nào cho persistedcột.

Nếu bảng được tạo lại với định nghĩa sau

CREATE TABLE dbo.persist_test (
      id            INT NOT NULL
    , id5p          AS (5 * id) PERSISTED
    , id5           AS (5 * id)
);

Sau đó, một yêu cầu cho một id5hoặc id5psẽ được thỏa mãn khi đọc phiên bản dữ liệu được duy trì thay vì thực hiện phép tính trong thời gian chạy để việc khớp xuất hiện (ít nhất là trong trường hợp này) theo thứ tự cột.

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.