Kalıcı bir hesaplanmış sütun seçtiğimde neden SQL Server “Compute Scalar”?


21

SELECTBu koddaki üç ifade

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;

bu planı oluştur:

Yürütme planı

SELECTKalıcı bir değer seçen final neden Hesaplamalı Skaler operatör üretir ?


3
Bkz. @ SqlKiwi'nin cevabı: Yürütme Planı neden, hesaplanan bir sütun için kullanıcı tanımlı bir işlev çağrısı içeriyor? . Sorgunuzda, tablodaki çıktı sütun listesi yalnızca [tempdb].[dbo].[persist_test].idve kalıcı olmasına rağmen değeri hesaplar.
Martin Smith

Yanıtlar:


14

Yorumlardaki deneysel bulguları özetlemek gerekirse, bu, aynı tabloda bir persistedve biri kalıcı olmayan ve ikisi de aynı tanıma sahip iki hesaplanmış sütun olduğunda ortaya çıkan bir uç durum gibi görünüyor .

Sorgu planında

SELECT id5p
FROM dbo.persist_test;

Tablo taraması persist_testyalnızca idsütunu yayar . Bir sonraki hesaplama skaleri, 5 ile çarpar ve id5bu sütunun sorguda bile referans edilmemesine rağmen çağrılan bir sütunu çıkarır. Son hesaplama skalar boyunca değeri alınır id5ve bir sütun olarak adlandırır id5p.

Sorgu Optimize Edici Derin Dalış - Bölüm 2'de açıklanan izleme işaretlerini kullanma (sorumluluk reddi: bu izleme bayrakları belgesiz / desteklenmez) ve sorguyu inceler

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

Çıktı verir

Proje Normalleştirmeden Önce Ağaç

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)

Proje Normalizasyonundan Sonra Ağaç

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

Dolayısıyla, hesaplanan tüm sütun tanımları genişletilir ve ardından Proje Normalleştirme aşamasında tüm özdeş ifadeler hesaplanan sütunlarla eşleştirilir id5ve bu durumda eşleşir . yani persistedsütuna herhangi bir tercih vermez .

Tablo aşağıdaki tanımla yeniden oluşturulmuşsa

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

Ardından , çalışma zamanında hesaplama yapmak yerine verilerin kalıcı sürümünü okumaktan ya id5da id5pbu istek yerine getirilmesinden dolayı, eşleştirme sütun sırasına göre (en azından bu durumda) gerçekleşir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.