Kimlik sütunundaki dizin kümelenmemeli mi?


19

Kimlik sütununa sahip bir tablo için, kimlik sütunu için kümelenmiş veya kümelenmemiş bir PK / benzersiz dizin oluşturulmalı mı?

Bunun nedeni, sorgular için diğer dizinlerin oluşturulmasıdır. Kümelenmemiş bir dizin (yığın üzerinde) kullanan ve dizin tarafından kapsanmayan sütunları döndüren bir sorgu, ek kümelenmiş dizin b-ağacı arama adımları olmadığından daha az mantıksal G / Ç (LIO) kullanır?

create table T (
  Id int identity(1,1) primary key, -- clustered or non-clustered? (surrogate key, may be used to join another table)
  A .... -- A, B, C have mixed data type of int, date, varchar, float, money, ....
  B ....
  C ....
  ....)

create index ix_A on T (A)
create index ix_..... -- Many indexes can be created for queries

-- Common query is query on A, B, C, ....
select A, B 
from T 
where A between @a and @a+5 -- This query will have less LIO if the PK is non-clustered (seek)

select A, B, C
from T 
where B between @a and @a+5 

....

Kimlik sütununda kümelenmiş PK iyidir çünkü:

  1. Monoton bir şekilde artar, böylece eklerken hiçbir sayfa ayrılmaz. Toplu bir eklemenin yığın (kümelenmemiş) bir tablodaki kadar hızlı olabileceği söylenir.

  2. Dar

Ancak, sorudaki sorgular kümelenmeden ayarlanmadan daha hızlı olacak mı?

** Güncelleme: ** Ya Iddiğer tabloların FK değeri varsa ve bazı sorgularda birleştirilecekse?


3
Daha iyi ya da daha kötü değil, duruma göre değişir.
Aaron Bertrand

1
@ ypercube kejser.org/clustered-indexes-vs-heaps bağlantısı , CI olmayanların daha az LIO'ya sahip olacağını söyledi.
u23432534

2
Geçmişte makaleyi okudum ve kesinlikle kümelenmiş bir dizin için vakalar ve bir yığın için vakalar olduğunu gösteriyor. Hepsi siyah ya da beyaz değil.
ypercubeᵀᴹ

4
@Ypercube'a verdiğiniz yanıtın, en azından paylaştığınız ayrıntılarla, Bay Kejser tarafından belirtilen kriterlerden herhangi birini karşıladığından emin değilim. Şu anki formunda, bunun faydalı bir cevap oluşturacağından emin değilim çünkü alıntı yaptığınız blog yayınında zaten yapılan neredeyse her senaryoyu kapsaması gerekir. Belirli bir senaryo hakkında daha fazla ayrıntı sağlayabilirseniz, belki de yazıdaki bazı bilgiler uygulanabilir.
swasheck

2
Aşağıdaki gibi şeylere bağlı olacaktır: a) iş yükü (OLTP? OLAP? Vb?), B) tablo boyutları, c) normal form, sadece birkaçını belirtmek için. Bu faktörlerden hiçbiriyle ilgili ayrıntı vermediniz, bu nedenle herhangi bir öneri, ortamınızdaki tahminlere dayanacaktır. Ayrıca, teklif ettiğiniz sorguları (temizlenmiş arabelleklerle) profillemeyi ve yapılandırma başına belirli G / Ç profillerini almayı ve kendiniz görmeyi denediniz mi?
swasheck

Yanıtlar:


16

Varsayılan olarak PK kümelenmiştir ve çoğu durumda bu iyidir. Ancak, hangi soru sorulmalıdır:

  • PK'm kümelenmeli mi?
  • kümelenmiş dizinim için hangi sütun (lar) en iyi anahtar olacak?

PK ve Kümelenmiş indeks 2 farklı şeydir:

  • PK bir kısıtlamadır. PK, satırları benzersiz bir şekilde tanımlamak için kullanılır, ancak depolama kavramı yoktur. Ancak, varsayılan olarak (SSMS'de), henüz kümelenmiş bir dizin yoksa benzersiz bir kümelenmiş dizin tarafından zorlanır.
  • Kümelenmiş dizinler, satır verilerini yaprak düzeyinde depolayan, yani her zaman kapsadığı anlamına gelen özel bir dizin türüdür. Anahtarın parçası olsun veya olmasın, tüm sütunlar yaprak düzeyinde saklanır. Benzersiz olması gerekmez, bu durumda kümelenmiş anahtara bir benzersizleştirici (4 bayt) eklenir.

Şimdi 2 soru ile karşılaşıyoruz:

  • Masamdaki (PK) satırları benzersiz bir şekilde nasıl tanımlamak istiyorum?
  • Bir dizinin yaprak düzeyinde nasıl saklamak istiyorum (Kümelenmiş Dizin)

Nasıl olduğuna bağlıdır:

  • veri modelinizi tasarlıyorsunuz
  • verilerinizi sorgularsınız ve sorgularınızı yazarsınız
  • verilerinizi ekler veya güncellersiniz
  • ...

İlk olarak, kümelenmiş bir dizine ihtiyacınız var mı? Toplu olarak eklerseniz, sıralanmamış verileri bir HEAP'ye (kümedeki sıralı verilere karşı) depolamak daha verimlidir. Satırları benzersiz bir şekilde tanımlamak ve sayfalarda depolamak için RID (Satır Tanımlayıcı, 8 bayt) kullanır.

Kümelenmiş dizin rastgele bir değer olmamalıdır. Yaprak seviyesindeki veriler indeks anahtarı tarafından saklanacak ve sıralanacaktır. Bu nedenle parçalanma veya sayfa bölünmesini önlemek için sürekli büyümelidir. Bu PK tarafından gerçekleştirilemezse, başka bir anahtarı kümelenmiş bir aday olarak düşünmelisiniz. Tanımlama sütunlarındaki, sıralı GUID'deki veya hatta ekleme tarihi gibi bir şeydeki kümelenmiş dizin, tüm satırlar son yaprak sayfasına ekleneceğinden, sıralı bir bakış açısından iyidir. Öte yandan, benzersiz tanımlayıcı bir PK olarak iş gereksinimleriniz için yararlı olsa da, kümelenmemelidir (rastgele sıralanır / oluşturulur).

Bazı veri ve sorgu analizlerinden sonra, kümelenmiş PK'da anahtar arama yapmadan önce verilerinizi almak için çoğunlukla aynı dizini kullandığınızı fark ederseniz, verilerinizi benzersiz bir şekilde tanımlamamasına rağmen bunu kümelenmiş dizin olarak düşünebilirsiniz.

Kümelenmiş dizin anahtarı, dizine eklemek istediğiniz tüm sütunlardan oluşur. Benzersiz bir sütun (4 bayt), üzerinde benzersiz bir kısıtlama yoksa (kopyalar için artan değer, aksi takdirde null) eklenir. Bu dizin anahtarı, daha sonra tüm kümelenmemiş dizinlerinizin yaprak düzeyinde her satır için bir kez saklanacaktır. Bazıları ayrıca birkaç kez indeks ağacının (B-ağacı) kökü ve yaprak seviyesi arasındaki ara seviyelerde (dal) saklanacaktır. Anahtar çok büyükse, kümelenmemiş tüm dizin büyür, daha fazla depolama alanı ve daha fazla IO, CPU, bellek, gerekir ... Ad + doğum tarihi + ülkesinde bir PK'niz varsa, bu anahtar büyük olasılıkla iyi bir aday değil. Kümelenmiş bir dizin için çok büyük. NEWSEQUENTIALID () kullanan benzersiz tanımlayıcı, sıralı olmasına rağmen genellikle dar bir anahtar (16 bayt) olarak değerlendirilmez.

Ardından, tablonuzdaki satırları nasıl benzersiz bir şekilde tanımlayacağınızı anladıktan sonra, bir PK ekleyebilirsiniz. Sorgunuzda kullanmayacağınızı düşünüyorsanız, kümelenmiş olarak oluşturmayın. Bazen sorgulamanız gerekiyorsa, başka bir kümelenmemiş dizin oluşturabilirsiniz. PK'nın otomatik olarak benzersiz bir dizin oluşturacağını unutmayın.

Kümelenmemiş dizinler her zaman kümelenmiş anahtarı içerecektir. Ancak, dizinlenmiş sütunlar (+ anahtar sütunlar) kapsayıcıysa, kümelenmiş dizinde herhangi bir anahtar araması olmaz. Kümelenmemiş bir dizine Include ve Where ekleyebileceğinizi unutmayın. (akıllıca kullanın)

Kümelenmiş dizin benzersiz olmalı ve mümkün olduğunca dar Kümelenmiş dizin zaman içinde değişmemeli ve aşamalı olarak eklenmelidir.

Şimdi tablo, kümelenmiş ve kümelenmemiş dizinler ve kısıtlamalar oluşturacak bazı SQL yazma zamanı.

Bunların hepsi teoriktir çünkü veri modelinizi ve kullanılan veri tiplerini bilmiyoruz (A ve B).


11

Kimlik sütununda birincil anahtarı (PK) olan bir tablo için, varsayılan olarak kümelenir. Kümelenmemiş kadar iyi olabilir mi?

Bir kimlik sütunundaki birincil anahtar için (özellikle) varsayılan anahtarın kümelenmemiş olup olmadığını soruyorsanız , hayır derim. Çoğu tablo kümelenmiş bir dizine sahip olmaktan yararlanır, bu nedenle birincil anahtar kısıtlaması için kümelenmeyi varsayılan yapmak, özellikle SQL Server'ın yeni kullanıcıları için genel olarak yardımcı olabilir.

Hemen hemen her seçenekte olduğu gibi, birinin diğerine göre tercih edileceği her zaman farklı koşullar vardır, ancak deneyimli bir DBA varsayılanın farkında olmalı ve uygun olduğunda geçersiz kılabilmelidir. Ayrıca ilgili S ve C'ye bakın, Birincil anahtar ne zaman kümelenmemiş olarak bildirilmelidir? .

Sorudaki sorgular kümelenmeden ayarlanmadan daha hızlı olacak mı?

Evet, ama uyarılarla.

RID aramaları aslında Anahtar aramalardan daha verimlidir. Gerekli tüm sayfalar bellekte olsa bile (büyük olasılıkla bir dizinin üst seviyeleri için), kümelenmiş dizin b ağacında gezinmeyle ilişkili bir CPU maliyeti vardır. Sonuç olarak, SQL Server genellikle CPU zamanı birimi başına Anahtar aramalardan çok daha fazla RID araması gerçekleştirebilir.

Uyarılar

Yukarıdaki tablo genellikle yığın olarak yapılandırılıp yapılandırılmayacağına karar verirken belirleyici bir faktör olmaz. Arama ortamlarından (kaplama dizinleri kullanarak) kaçınmanın pratik olmaması gerekir ve donanım ortamı ve iş yükü göz önüne alındığında, arama sayısının performans üzerinde ölçülebilir (ve önemli) bir etkiye sahip olacak kadar büyük olması gerekir.

Bu cevapta öbeğin kümelenmiş dizin tartışmasına karşı tüm yönlerini kapsamak gerçekten pratik değildir, ancak genel olarak bir tabloyu bir yığın olarak yapılandırmayı tercih etmenin nispeten az iyi nedenleri olduğunu söyleyeceğim. Benim için, soruda önerilen tasarım türünü seçmek, uygulamadan önce çok dikkatli bir analiz yapılmasını gerektirecek ve yüksek bir barla buluşmak zorunda kalacaktı. 'Ölçeklenebilirlik' hakkında genel argümanlar yeterli olmaz.

Birleşimlerle ilgili soruya ilişkin güncellemeyle ilgili olarak, kümelenmiş dizini kaybetmenin yürütme planları üzerindeki etkisinin değerlendirilmesi, yukarıda belirtilen analizin bir parçasını oluşturacaktır. İç içe döngüler birleşimleri kullanılıyorsa, satırdaki tüm sütunlar arama yapılmadan hemen kullanılabilir olduğundan, kümelenmiş dizinin birleştirme anahtarında bulunması çok uygundur.

Kendi deneyimim, kimlik sütunlarında benzersiz kümelenmiş dizinlere sahip olmanın çok yararlı olduğu, her şeyin dikkate alındığı oldu. Alan yönetimi açısından yığınları sorunlu buldum ve ayrıca bazı SQL Server özelliklerinin çalışması için benzersiz bir kümelenmiş dizin gerektirdiğini belirtmek gerekir .


8

Aslında, Benzersiz Dizinler ve Benzersiz Olmayan Dizinler işi işleyebileceğinden, Kümelenmiş bir Dizin veya Birincil Anahtar oluşturmanıza gerek yoktur. SQL Server, en az 1.1 sürümünden beri Kümelenmiş bir Dizini desteklemiştir, ancak Birincil Anahtar yalnızca programcıların benzersiz bir dizin tanımlayarak zorladığı bir "kavram" dır.

Ancak, hem Birincil Anahtarların hem de Kümelenmiş Dizinlerin, veritabanlarının çoğunda değerli kavramlar olduğu görülmektedir.

Aşağıda gösterildiği gibi bazı indeksleme seçeneklerinin kısmi açıklamalarını görmek için SQL Server belgelerine bakalım.

Kümelenmiş Dizin: https://msdn.microsoft.com/en-us/library/ms190457.aspx

  • Kümelenmiş dizinler, veri satırlarını anahtar değerlerine göre tablo veya görünümde sıralar ve depolar. Bunlar dizin tanımında yer alan sütunlardır.
  • Tablo başına yalnızca bir kümelenmiş dizin olabilir

Birincil Anahtar: https://msdn.microsoft.com/en-us/library/ms190457.aspx

  • Bir tablo yalnızca bir PRIMARY KEY kısıtlaması içerebilir.

  • Bir PRIMARY KEY kısıtlaması içinde tanımlanan tüm sütunlar NOT NULL olarak tanımlanmalıdır.

  • Birincil Anahtar, Kümelenmiş Dizin (Kümelenmiş Dizin yoksa varsayılan) veya Kümelenmemiş Dizin olarak oluşturulabilir.

Benzersiz Dizin: https://msdn.microsoft.com/en-us/library/ms187019.aspx

  • Bir UNIQUE kısıtlaması oluşturduğunuzda, varsayılan olarak bir UNIQUE kısıtlamasını uygulamak için benzersiz bir kümelenmemiş dizin oluşturulur.

  • Tablo için bir Kümelenmiş Dizin yoksa, BENZERSİZ Bir Kümelenmiş Dizin belirtebilirsiniz.

Bu, Kümelenmiş Dizinler ve Birincil Anahtarlar hakkındaki sorunuzun gerçekten aşağıdaki sorunlardan bazılarıyla ilgili olduğu anlamına gelir. Her tablonun aynı indeksleme planından faydalanmadığını lütfen unutmayın.

Birincil Anahtarın Kümelenmiş Dizin'den ayrı olmasından ne zaman yararlanabilirim?

Kümelenmiş Dizin Geniş olduğunda (örneğin, 5 sütunluk metin bilgisi, ancak Birincil Anahtar küçük (INT veya BIGINT) gibi, açıkladığınız gibi.

  • Geniş bir Kümelenmiş Dizin, Kümelenmiş Dizin'den ( Tablo olarak da bilinir ) seri yanıtlar sağlayan bir sorgu alt kümesi için dizinden satırları hızlı bir şekilde seçmenize olanak tanır . Örneğin, 5 sütunlu Kümelenmiş Dizin C1, C2, C3, C4, C5 veya C1, C2, C3, C4 ve benzeri sütunların C1'e kadar taranmasını destekleyebilir.
  • Not: Satırlar büyükse, bu , özellikle tablodaki diğer sütunlar sonuç kümesine düzenli olarak dahil edilmişse , seri satır kümesini seçmede size bazı hız avantajları sağlayabilir .
  • Bu durumda , diğer tablolardaki satırları sınırlamak için bir Yabancı Anahtar olarak gereken değeri sağlamak amacıyla referans bütünlüğü için Birincil Anahtar'ı kullanabilirsiniz . PK küçüktür ve bu nedenle FK referans verilen tabloların büyüklüğünde küçük bir vuruştur.
  • Ancak, Kümelenmiş Dizin içeren bir tabloda oluşturulan tüm dizinlerin, bu tabloda oluşturduğunuz diğer dizinlerdeki tüm küme sütunlarını içereceğini unutmayın. Geniş bir Kümelenmiş Dizin, o tablodaki kümelenmemiş tüm dizinlerin boyutunu genişletir.

Birincil Anahtarı Kümelenmiş Dizin haline getirmeli misiniz?

  • Küçük Birincil Anahtarınız (INT veya BIGINT) varsa ve Kümelenmiş Dizin ise, küme sütunlarının ek yükü nispeten küçüktür. Bu durumda Kümelenmiş Birincil Anahtar, bu tablodaki her dizinde de bulunsa da, yukarıda tartışılan Geniş Küme'den daha düşük bir ücrettir.

  • Bu Birincil Anahtar Kümelenmiş Dizini genellikle doğrudan birçok satırı seri olarak seçmek için kolay bir yol sunmaz.

  • Kümelenmiş Birincil Anahtar oluşturduğunuza göre, bir zamanlar Kümelenmiş Dizine eklemeyi planladığınız diğer sütunlara ne dersiniz ?

  • C1, C2, C3, C4, C5 sütunlarının geniş arama ölçütlerini dizine eklemek için gerektiğinde Benzersiz (veya Benzersiz Olmayan) bir dizin oluşturun. Bu “Taklit Kümelenmiş” Endeksindeki değerler, bu 5 sütun için daha hızlı bir arama yolu görevi görebilir. Dizine eklenmemiş veya düzenli olarak seçilen iki sütun varsa, bunlar ile dizine eklenebilir INCLUDE (Doctor_Name, Diagnosis_Synopsis).

Basit Kümelenmiş Dizinleri ve Birincil Anahtarları kullanışlı bulmama rağmen, bunları bir tabloda mı yoksa bir veritabanında mı kullanacağınızı düşünmenin bazı iyi nedenleri vardır.

Kümelenmiş bir Endekse ihtiyacınız var mı?

  • Dizinler (Benzersiz Dizinler ve Benzersiz Olmayan Dizinler) oluşturup Kümelenmiş Dizin olma yükü olmadan Birincil Anahtarı tanımlarsanız, daha dar dizinlerin sorgularınız için gerekenleri sağladığını görebilirsiniz.

  • Kümelenmiş Dizinler ve Birincil Anahtarlarda bazı yararlı davranışlar vardır, ancak bunun gerçekten en önemli dizinler olduğunu unutmayın. Uygulamanızın gerçeklerini hesaba katacak şekilde dizin oluşturma stratejisini tasarlayın. Belki de OneBigTabletabloların çoğu için kullandığınızdan farklı bir dizin oluşturma stratejisine sahip olmanız gerekir.

  • Kümelenmiş Dizin olmadan verileriniz , hiç de iyi bir arama mekanizması olmayan Satır Tanımlayıcısı (RID) ile bir yığın olarak depolanır . Ancak, daha önce de belirtildiği gibi, sorgularınızı ele almak için benzersiz ve benzersiz olmayan dizinler oluşturabilirsiniz.

Şimdi sizi Yığınları düşünmeye götürüyor:

Yığınlar ve Dizinler: https://msdn.microsoft.com/en-us/library/hh213609.aspx

  • Bir tablo yığın olarak saklandığında, tek tek satırlar, dosya numarası, veri sayfası numarası ve sayfadaki yuvadan oluşan bir satır tanımlayıcısına (RID) referans olarak tanımlanır. Satır kimliği küçük ve etkili bir yapıdır. (Ama bu bir endeks değil .)
  • Bazen, veri kümelenmemiş dizinlerle her zaman erişildiğinde ve RID kümelenmiş bir dizin anahtarından daha küçük olduğunda veri mimarları yığın kullanır .

Ancak, büyük bir veri kümesinde bazı 'sıcak noktalar' varsa, başka bir dizin türüne de bakabilirsiniz:

Filtrelenmiş Dizin: https://msdn.microsoft.com/en-us/library/cc280372.aspx

  • İyi tasarlanmış filtrelenmiş bir dizin, tam tablo kümelenmemiş bir dizinden daha küçük olduğundan ve filtrelenmiş istatistiklere sahip olduğundan sorgu performansını ve yürütme planı kalitesini artırır. Filtrelenen istatistikler, yalnızca filtrelenmiş dizindeki satırları kapsadığı için tam tablo istatistiklerinden daha doğrudur .

  • Filtrelenmiş dizinler, filtrelenmiş dizinlere bağlantıda özetlenen bir dizi kısıtlamaya sahiptir.

Bununla birlikte, Birincil Anahtarları ve Kümelenmiş Dizinleri birlikte atlama olasılığını düşünmek istiyorsanız, Markus Winand'ın aşağıda bağlantılı gönderisini okuyabilirsiniz. Bazı kod örnekleri ile, bu özellikleri kullanmaktan vazgeçmenin iyi bir fikir olabileceğini öne sürmek için nedenlerini göstermektedir.

http://use-the-index-luke.com/blog/2014-01/unreasonable-defaults-primary-key-clustering-key

Ancak hepsi sonunda uygulamanızı anlamanıza ve kod, tablolar, dizinler vb. Tasarladığınız işe uygun şekilde tasarlanmaya geri dönüyor.


Değer için ne olursa olsun, günlük işimde bir yığın olan bir tablo bulursam, büyük olasılıkla bir hata olduğunu düşünür ve geliştiricilerle bir yığın yapılıp yapılmadığını görmek için kontrol ederim.
RLF

-2

Dikkate alınması gereken birkaç nokta.

Monoton bir şekilde artan bir değer üzerindeki bir dizin (kümelenmiş ya da değil), toplu eklemeler sırasında sayfa bölünmelerini kaydederken, dizinin kuyruk ucunda yeni bir etkin nokta oluşturur. Tek bir iş parçacığı toplu eki ile ilgili bir sorun olmasa da, iş parçacıkları dizinin son sayfasına erişmek için sürekli olarak rekabet edeceğinden, çok parçacıklı bir uygulamanın yüksek oranda yeni yerleştirilmesi için çekişmeyi kesinlikle artıracaktır.

Tabloyu bir vekil (kimlik) PK'ye dayalı olarak kümelemek nadiren faydalıdır. Böyle bir birincil anahtar çoğunlukla tek tek tuple'lara teker teker erişmek için veya tüm dizini birleşimler için taramak için kullanılır. Her iki durumda da dizinin kümelenip kümelenmemesi önemli değildir (birleştirme birleşmeleri dışında olabilir, ancak ne sıklıkta görülür?)

Ben en çok anahtar aralığı tarama isteyen sorgular ve diğer sütunları referans ek tahmin kapsayan kümelenmiş bir dizin yarar sağlayacağını düşünüyorum.


Bunun bir sorun haline gelmesi için oran ne kadar yüksek olmalı?
ypercubeᵀᴹ

@ ypercube "değişir" diyebilir miyim? Çünkü öyle. Tabloda tetikleyicilerin yokluğunda, saniyede 1K eklemeli bir düzine iplik ile bir çekişme yaşamaya başlamayı beklerdim.
mustaccio

Örnek olay
mustaccio

Katılmıyorum ama tek bir sıcak nokta ile ne kadar ileri gidebileceğini soruyordum. CI olarak IDENTITY (bellek bana iyi hizmet veriyorsa) içeren bir tabloya saniyede 30 bin satır ekleme hakkında bir makale gördüğümü hatırlıyorum, ancak blog gönderisini bulamıyorum.
ypercubeᵀᴹ

Bu tartışma, belirli bir donanımda somut bir şemaya karşı çalışan somut bir iş yükü olmadığında anlamsızdır. Umarım hepimiz monoton bir şekilde artan bir dizinin bir "sıcak nokta" yaratacağına katılabiliriz; kabul edilemez bir darboğaz yaratıp yaratmayacağı ve kişinin buna önem verip vermeyeceği koşullara bağlıdır.
mustaccio
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.