Kümelenmiş Dizin Seçimi - PK veya FK?


11

Aşağıdaki gibi görünen bir SQL Server 2014 tablo var:

OrderId     int           not null IDENTITY --this is the primary key column
OrderDate   datetime2     not null
CustomerId  int           not null
Description nvarchar(255) null

Ekibimdeki bazı kişiler kümelenmiş dizinin açık olması gerektiğini önerdiler OrderId, ancak aşağıdaki nedenlerden dolayı CustomerId+ OrderId'nın daha iyi bir seçim olacağını düşünüyorum :

  • Hemen hemen tüm sorgular görünecek WHERE CustomerId = @param, değilOrderId
  • CustomerIdCustomertablonun yabancı bir anahtarı olduğundan, kümelenmiş bir dizine sahip CustomerIdolmak birleştirmeleri hızlandırmalıdır
  • İken CustomerIdbenzersiz değil, ek sahip OrderIdendekste belirtilen sütun (Biz kullanabilirsiniz benzersizliği sağlayacak UNIQUEolanlar 2 sütun üzerinde kümelenmiş bir dizin oluştururken benzersizliğini olmamasından yükünü önlemek için, anahtar kelime)
  • Veri eklendikten sonra, CustomerIdve OrderIdasla değişmez, bu nedenle bu satırlar ilk yazma işleminden sonra hareket etmez.
  • Veri erişimi, varsayılan olarak tüm sütunları isteyen bir ORM aracılığıyla gerçekleşir, bu nedenle dayalı bir sorgu CustomerIdgeldiğinde, kümelenmiş dizin herhangi bir ek çalışma olmadan tüm sütunları sağlayabilir.

Mu CustomerIdve OrderIden iyi seçenek gibi yaklaşım ses yukarıda verilen? Veya OrderIdtek başına daha iyi, çünkü tek başına bir tekliği garanti eden tek bir sütun mu?

Şu anda, tablonun üzerinde kümelenmiş bir dizin OrderIdve kümelenmemiş bir dizin var CustomerId, ancak kapsam dahilinde değil, bu nedenle bir ORM kullandığımız ve tüm sütunlar istendiğinden, bunları almak için fazladan bir çalışma var. Bu yazı ile performansı daha iyi bir CI ile geliştirmeyi düşünmeye çalışıyorum.

DB'mizdeki etkinlik yaklaşık% 85 okuma ve% 15 yazmadır.

Yanıtlar:


5

Topluluk wiki yanıtı :

İlk sütun olarak CustomerID ile bileşik kümelenmiş bir dizin anahtarı en iyi olacağını düşünüyorum, çünkü WHEREneredeyse tüm sorguların yan tümcesinde.

Artan bir anahtara göre daha fazla bölünme olabilir (veya 'kötü' bölünmelerden kaçınmak için doldurma faktörünü yönetir ve sürdürürseniz , bir süre daha düşük sayfa yoğunluğu olabilir ). Bununla birlikte, anahtar aramalardan kaçınıldığından, müşteri sorguları için genel performans artışı önemlidir.

OrderID veya OrderDate , en kritik sorgularınıza bağlı olarak ikinci sütun için en iyisi olabilir.

Örneğin, müşteriler bir web sitesine giriş yaptıktan sonra son siparişlerin kronolojik bir listesini görürse , optimize etmek için Sırada OrderDate olmalıdır ORDER BY OrderDate DESC.

Kümelenmiş dizin olarak CustomerID üzerinde kümelenmemiş bir dizinle OrderID'yi seçerseniz , yalnızca kümelenmemiş dizinde bölme ve parçalanma elde edersiniz.


3

Bu tablo çok yoğun yazılıyorsa (örneğin , buna karşı ifadelerden INSERTçok daha fazla SELECTifade oluyor), wiki cevabına katılmayacağım .

Kompozit kümelenmiş anahtarın ilk sütunu olarak CustomerID seçildiğinde çok sayıda orta sayfa bölünmesi elde edilir . Umarım çok sayıda mevcut müşteriniz olur ve her zaman birçok yeni müşteri alırsınız. Müşteriler (umarım) işletmeniz büyümeye devam ederken birden fazla sipariş verdiklerinden, bu yaklaşım sadece yazmalarda değil, aynı zamanda dizinlerinizin de ağır bir şekilde parçalanacağından, ve muhtemelen daha fazla miktarda beyaz alan içerir (bu da boşa depolama ve bellek anlamına gelir).

MüşteriNo'nun bileşik kümelenmiş bir dizinin önde gelen sütunu olması gerektiğini düşünüyorsanız, FILLFACTORbu tablo için tüm dizinleri ayarlayarak orta sayfa bölünmelerinin etkisini azaltabilirsiniz . Bu, tablonun / dizinin boyutunu artırarak orta sayfa bölünmelerini azaltır. Bu rotaya gitmek istiyorsanız, 80 değeri ile test etmenizi ve analizin orta sayfa bölünmelerinin hala performansı öldürdüğünü ortaya çıkarmasını azaltmanızı öneririm .

Benim önerim OrderId kullanmak. OrderID doğal olarak sıralı olmalı ve tablo büyümesi ile iyi ve beklenen son sayfa bölünmelerini üretmelidir. Ayrıca , OrderDate sütununu bir bölüm anahtarı olarak kullanmayı seçerseniz, bu yaklaşım Tablo Bölümleme ile daha iyi oynar. Sürekli olarak MüşteriNo alanını kullanan sorgularla ilgili olarak, bu sorguları işlemek için kümelenmemiş bir dizin oluşturun. Bu dizinin, FILLFACTORyukarıda bahsettiğim orta sayfa bölünmelerinden muzdarip olacağı için uygun şekilde tanımlanması gerekir , ancak bölünmeler kümelenmiş dizine karşı meydana gelip gelmediğinden farklı olarak genel olarak kötü olmayacaktır.

DB'mizdeki etkinlik yaklaşık% 85 okuma ve% 15 yazmadır.

CustomerID+ OrderID(ve bölünmeler olmadan büyümeye izin vermek için bir dolgu faktörünün belirtilmesi), bu değerlendirme geçerliyse muhtemelen daha iyidir. Sadece yapmak emin değerlendirme doğru olduğunu. Test testi testi.


1
Bir sayfaya son (veya yalnızca) Müşteri için sipariş eklemenin "orta sayfa bölünmesi" olmadığını unutmayın. Bu nedenle, müşteri başına Siparişler yüksekse veya satır genişliği büyükse, daha az Sipariş eki için "orta sayfa bölünmeleri" gerekir.
David Browne - Microsoft
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.