Kalıcı Olmayan Hesaplanmış Sütun SQL Server'da Kümelenmemiş Dizin Oluşturma


10

SQL Server'ın kalıcı olmayan bir hesaplanmış sütunu nasıl sakladığına dair herhangi bir belge bulmakta zorlanıyorum.

Aşağıdaki örneği alın:

--SCHEMA
CREATE TABLE dbo.Invoice
(
    InvoiceID INT IDENTITY(1, 1) PRIMARY KEY,
    CustomerID INT FOREIGN KEY REFERENCES dbo.Customer(CustomerID),
    InvoiceStatus NVARCHAR(50) NOT NULL,
    InvoiceStatusID AS CASE InvoiceStatus 
                         WHEN 'Sent' THEN 1 
                         WHEN 'Complete' THEN 2
                         WHEN 'Received' THEN 3
                       END
)
GO

--INDEX
CREATE NONCLUSTERED INDEX IX_Invoice ON Invoice
(
    CustomerID ASC
)
INCLUDE
(
    InvoiceStatusID
)
GO

Yaprak seviyesinde saklandığını anlıyorum, ancak değer kalıcı değilse, bir şey nasıl saklanır? Dizin, SQL Server'ın bu durumda bu satırları bulmasına nasıl yardımcı olur?

Herhangi bir yardım büyük takdir,

Çok teşekkürler,

DÜZENLE:

Brent & Aaron'a bunu cevapladığı için teşekkürler, işte PasteThePlan açıkladıklarını açıkça gösteriyor.


5
Tablonun veri sayfalarında kalıcı olmaz, ancak dizin sayfalarında kalıcıdır .
Aaron Bertrand

Kalıcı olmayan Hesaplanan sütunlar tabloda fiziksel olarak depolanmaz. Bunlar sanal sütunlardır. Bir sorguda her başvuru yapıldığında değerleri yeniden hesaplanır. bkz bu ref .
Kin Shah

Yanıtlar:


11

SQL Server, hesaplanan alanda dizin oluşturduğunda, hesaplanan alan o anda diske yazılır - ancak bu dizinin yalnızca 8K sayfasında. SQL Server, InvoiceStatusID değerini kümelenmiş dizin üzerinden okurken hesaplayabilir - bu verileri kümelenmiş dizine yazmaya gerek yoktur.

Dbo.Invoice içinde satırları sildiğiniz / güncellediğiniz / eklediğinizde, dizinlerdeki veriler güncel tutulur. (InvoiceStatus değiştiğinde, SQL Server IX_Invoice'i de güncellemeyi bilir.)

Bunu kendiniz görmenin en iyi yolu aslında bunu yapmaktır: bu nesneleri oluşturun ve InvoiceStatusID alanına dokunan güncellemeleri yürütün. Dizin güncellemelerinin nerede olduğunu görmek için yardım istiyorsanız, yürütme planını (PasteThePlan.com yardımcı olur) gönderin.


1
@ Uberzen1 Hayır, açıkladığı gibi, ekleme / güncelleme zamanında dizin sayfalarına yazılır. Dizin sütuna erişmek için kullanılırsa hiçbir şeyi yeniden hesaplaması gerekmez.
Aaron Bertrand

Ah! Şimdi seninleyim üzgünüm!
Uberzen1

6
@blobbles iyi, suç yok, ama Brent'te olduğunu sanmıyorum. Aynı XML'yi dropbox'a, MSDN forumlarına, burada, temelde çevrimiçi olan her yere yapıştırabilirler ... şimdi her çevrimiçi hizmetin, orada dosya yükleyen kişiler tarafından açığa çıkarılabilecek sırlardan sorumlu olması gerekiyor mu?
Aaron Bertrand

2
@blobbles evet, insanların aşırı paylaşımını engelleyemezsiniz. Hey, bu arada, beni Instagram'da takip et - Ben BrentO'yum - ve orada kahvaltımın fotoğraflarını paylaşıyorum. ;-)
Brent Ozar

4
Gizlilik bağlantısındaki @blobbles şunu belirtir: Buraya kopyaladığınız / yapıştırdığınız veriler herkese açıktır . Herkes okuyabilir. Güvenlik yok.
ypercubeᵀᴹ

8

Dizinlenmiş, kalıcı olmayan hesaplanmış bir sütunun değeri tablonun veri sayfalarında kalmaz, ancak dizin sayfalarında kalır . 0, 1 veya birden çok dizinde kalıcı olup olmadığına bakılmaksızın tabloda kalıcı değildir.

Brent'in açıklamasını göstermek için, verdiğiniz örneği alarak, bir satır ekleyelim:

INSERT dbo.Invoice(CustomerID, InvoiceStatus) VALUES(1,N'Sent');

Şimdi dizin sayfalarına bakalım:

DBCC TRACEON(3604, -1);
DBCC IND(N'dbname', N'dbo.Invoice', 2);

(Açıkçası değiştirin dbnameve durumunuzda dizin kimliği 2 olmayabilir.)

Çıktı (sizinki kesinlikle farklı olacaktır):

resim açıklamasını buraya girin

Ve son olarak, sayfayı PageType2 için inceleyelim :

DBCC PAGE(7, 1, 584, 3);

(Büyük olasılıkla veritabanı kimliğinizle eşleşmesi için 7 değerini değiştirmeniz gerekir ve birden fazla veri dosyanız varsa, ikinci argümanı PageFIDilk sonuçtan eşleşecek şekilde değiştirmeniz gerekebilir .)

Çıktı:

resim açıklamasını buraya girin

Dizin sayfasında.


Çok iyi, teşekkürler Aaron. Soruyu başlangıçta sormamın nedeni, gerçek dünyada benzer bir dizini konuşlandırırken gerçek bir sorun yaşıyorum ve konuyu anlayabilmek için kaputun altında neler olup bittiğini tam olarak anlamak istedim. Bu çok yardımcı oluyor, teşekkürler!
Uberzen1

1
@ Uberzen1 "Gerçek bela" tanımlayabilir misiniz? Bu sorun hakkında bir soru gönderecek misiniz?
Aaron Bertrand

Yapabilirim, önce kendimi biraz daha inceleyecektim, ancak sadece indeks oluşturma ifadesinin tam olarak ne yaptığını araştırmak istedim. TLDR; Yukarıdaki faturalar tablosuna benzer büyük bir tablo var, yaklaşık 400m kayıtları var ve ne yazık ki OrderStatus sütun tam ortasına tokatladı, endeksleme vb biraz acı verici. Nihayetinde varchar alanını kendi tablosuna taşıyacağımız ve hesaplayacağımız için hesaplanmış bir sütun ekledik. 1/2
Uberzen1

5
@ Uberzen1 Evet, hesaplanan sütun aslında dizine yazılırken diske yerleştirildiğinden, tüm bu etkinliklerin günlüğe kaydedilmesi gerekir. Çözüm, hesaplanan sütuna güvenmeyi durdurmak olabilir - ya bu ifadeyi bir görünüme ya da geçici sorgulara yerleştirin ve bu bir seçenek değilse, yeni bir boş sütun oluşturabilirsiniz, parçacıklar halinde güncelleyin (günlük öldürmeyi önlemek için) , hesaplanan sütunu bırakın, yeni sütunu yeniden adlandırın ve DML'nizi manuel olarak yazmak için değiştirin. Ama gerçekten mevcut verilerden türetebileceğiniz gereksiz bilgi olduğundan, ilk seçeneği tercih ederim.
Aaron Bertrand

2
Çok teşekkürler Aaron. Önüne bir bakış attığından bahsettiğinize sevindim, çünkü benim çözümüme de gidiyorum, belki de bu fikri tekrar ziyaret etmenin zamanı geldi!
Uberzen1

7

PERSISTEDHesaplanan bir sütunun niteliği , değerlerin dizinde kalıcı olup olmadığı değil , tabloda (kümelenmiş dizin veya yığın) devam edip etmediği ile ilgilidir .

CREATE INDEXHesaplanan sütunlar ve endeksler ilişkin sınırlamalar için gereksinimleri vardır:

Belirleyici ve kesin ya da kesin olmayan hesaplanmış sütunlar sütunları içerebilir. Görüntü, ntext, metin, varchar (max), nvarchar (max), varbinary (max) ve xml veri türlerinden türetilen hesaplanmış sütunlar, hesaplanan sütun veri türlerine dahil olduğu sürece anahtar olmayan sütunlara dahil edilebilir sütunu. Daha fazla bilgi için, bkz. Hesaplanan Sütunlar hakkında Dizinler.

Hesaplanan sütunun kalıcı olup olmadığı konusunda herhangi bir sınırlama yoktur.

ve daha fazlası (bir dizinin ana bölümünde yaklaşık olarak değil, hesaplanan sütunlar hakkında):

Dizinler hesaplanan sütunlarda oluşturulabilir. Ayrıca, hesaplanan sütunlar özelliğe sahip olabilir PERSISTED. Bu, Veritabanı Altyapısı'nın hesaplanan değerleri tabloda sakladığı ve hesaplanan sütunun bağlı olduğu diğer sütunlar güncellendiğinde bunları güncellediği anlamına gelir. Veritabanı Altyapısı, bu kalıcı değerleri sütunda bir dizin oluşturduğunda ve bir sorguda dizine başvurulduğunda kullanır.

Hesaplanan bir sütunu indekslemek için hesaplanan sütunun deterministik ve kesin olması gerekir. Ancak, PERSISTEDözelliği kullanmak, dizinlenebilir hesaplanmış sütun türünü içerecek şekilde genişletir:

...

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.