Kümelenmiş ve Kümelenmemiş


98

Alt düzey SQL bilgim (Server 2008) sınırlıdır ve şimdi DBA'larımız tarafından sorgulanmaktadır. Senaryoyu açıklamama izin verin (haklı olduğumu umarak bariz ifadelerden bahsetmiştim, ancak yanlış bir şey görürseniz lütfen söyleyin) senaryoyu:

İnsanlar için 'Mahkeme Kararları' tutan bir masamız var. Tabloyu oluşturduğumda (Ad: CourtOrder), şu şekilde oluşturdum:

CREATE TABLE dbo.CourtOrder
(
  CourtOrderID INT NOT NULL IDENTITY(1,1), (Primary Key)
  PersonId INT NOT NULL,
  + around 20 other fields of different types.
)

Daha sonra birincil anahtara kümelenmemiş bir dizin uyguladım (verimlilik için). Nedenlerim, bunun benzersiz bir alan (birincil anahtar) olması ve sık sık yaptığımız gibi, esas olarak seçim amacıyla dizine eklenmesiSelect from table where primary key = ...

Daha sonra Kişi Kimliğine KÜMELENMİŞ bir dizin uyguladım. Bunun nedeni, belirli bir kişi için siparişleri fiziksel olarak gruplamaktı, çünkü işin büyük çoğunluğu bir kişi için sipariş alıyor. Yani,select from mytable where personId = ...

Şimdi bunun üzerine çekildim. Kümelenmiş dizini birincil anahtara ve normal dizini kişi kimliğine koymamız gerektiği söylendi. Bu bana çok garip geliyor. Öncelikle, neden benzersiz bir sütuna kümelenmiş bir dizin koyarsınız? ne kümeleniyor? Kuşkusuz bu kümelenmiş dizinin israfı mı? Benzersiz bir sütunda normal bir indeksin kullanılacağına inanırdım. Ayrıca, dizini kümelemek farklı bir sütunu kümeleyemeyeceğimiz anlamına gelir (Tablo başına bir tane, değil mi?).

Bir hata yaptığımın söylenmesinin nedeni, Kişi Kimliği'ne kümelenmiş bir dizin koymanın ekleri yavaşlatacağına inanmalarıdır. Bir seçimin hızındaki% 5'lik artış için, ekleme ve güncellemelerde hızda% 95'lik bir düşüş elde ediyor oluruz. Bu doğru ve geçerli mi?

Kişi kimliğini kümelediğimiz için SQL Server'ın, Kişi Kimliğine bir değişiklik yaptığımızda veya eklediğimizde verileri yeniden düzenlemesi gerektiğini söylüyorlar.

Öyleyse sordum, SQL neden bu kadar yavaşsa KÜMELİ DİZİN konseptine sahip olsun? Söyledikleri kadar yavaş mı? Optimum performansı elde etmek için indekslerimi nasıl kurmalıyım? SELECT'in INSERT'ten daha fazla kullanıldığını düşünmüştüm ... ama INSERTS'de kilitleme sorunları yaşadığımızı söylüyorlar ...

Umarım birisi bana yardım edebilir.


Yanıtlar:


117

Kümelenmiş ve kümelenmemiş dizin arasındaki fark, kümelenmiş dizinin veritabanındaki satırların fiziksel sırasını belirlemesidir . Başka bir deyişle, kümelenmiş dizinin uygulanması, PersonIdsatırların PersonIdtabloda fiziksel olarak sıralanacağı anlamına gelir; bu, bu konuda bir dizin aramasının doğrudan satıra gitmesine izin verir (sizi satırın satırına yönlendirecek olan kümelenmemiş bir dizin yerine konum, fazladan bir adım ekleyerek).

Bununla birlikte , birincil anahtarın kümelenmiş dizin olmaması, ancak duyulmamış olmaması olağandışıdır . Senaryonuzla ilgili sorun aslında varsaydığınızın tam tersidir: Kümelenmiş bir dizinde yinelenen değil benzersiz değerler istiyorsunuz . Kümelenmiş dizin, satırın fiziksel sırasını belirlediğinden, dizin benzersiz olmayan bir sütundaysa, sunucunun yinelenen anahtar değerine sahip satırlara bir arka plan değeri eklemesi gerekir (sizin durumunuzda, aynı satıra sahip tüm satırlar) PersonId) böylece birleşik değer (anahtar + arka plan değeri) benzersiz olur.

Ben edilir önermek tek şey değil bir vekil anahtarı (sizin kullanarak CourtOrderIdyerine birincil anahtar olarak) sütunu, ama bir bileşik birincil anahtar kullanmak PersonIdsütunların ve diğer bazı benzersiz tanımlayıcı sütunu veya set. Bu mümkün değilse (veya pratik değilse), kümelenmiş dizini üzerine koyun CourtOrderId.


Teşekkürler Adam. Öyleyse, kümelenmiş bir dizin ne zaman yararlı olur? Kümelenmiş dizinin faydasının, örneğin çoğu sorgunun bir PersonID'de olduğu zamanlar için verileri gruplamak olduğunu düşündüm ... böylece veriler gruplandırılacaktı.
Craig

3
O edilir değil fiziksel olarak sıralama kriteri PersonId. Mantıksal olarak sıralanır PersonId, mantıksal ve fiziksel düzen arasındaki herhangi bir tutarsızlık, mantıksal parçalanma derecesidir.
Martin Smith

1
@cdotlister Bir dizinin yararı , verileri gruplamak değil sıralamaktır (bu, dizin içinde yinelenen verileri ima eder). Ayrım anlamsal görünse de, kümelenmiş dizinler söz konusu olduğunda değildir. Mümkünse, kümelenmiş dizin, satırı benzersiz bir şekilde tanımlayan bir şey üzerinde olmalıdır ve (ideal olarak) aynı zamanda en sık sorgulanan sütun veya sütun kümesidir. Bu nedenle genellikle birincil anahtarda bulunur.
Adam Robinson

1
@CyberSluethOmega: Bilmiyorum; Sorunuz karar vermem için yeterli bilgi içermiyor. Tablonun sonundan farklı olarak satırların sıklıkla eklendiği veya silineceği bir dizi sütun üzerinde kümelenmiş bir dizin ister miyim ? Hayır. Ama bunu neden sorduğundan ya da neden olumsuz oy kullandığından emin değilim.
Adam Robinson

1
@CyberSluethOmega: İnternet, yorumların bu şekilde tasarlanmadıklarında savunma amaçlı veya soğuk görünmesine neden olabilir. Kümelenmiş dizini birincil anahtardan başka bir şey yapmadığımı, aslında böyle bir şey söylemediğimi söylediğimi iddia ettiniz. Aslında ne dedim oldu "bu sıradışı ... ama duyulmamış değil", ki ben anlama geldiğini do Bu yapıldığında vaka biliyoruz.
Adam Robinson

14

Ben kesinlikle bir SQL Uzmanı değilim ... bu yüzden bunu bir DBA görünümü yerine geliştiricinin görüşü olarak alın ..

Sıralı düzende olmayan kümelenmiş (fiziksel olarak sıralı) dizinler üzerindeki eklemeler, eklemeler / güncellemeler için fazladan çalışmaya neden olur. Ayrıca, aynı anda birçok ekiniz varsa ve hepsi aynı yerde gerçekleşiyorsa, çekişme ile sonuçlanırsınız. Özel performansınız, verilerinize ve bunlara nasıl eriştiğinize bağlı olarak değişir. Genel kural, kümelenmiş dizininizi tablonuzdaki en benzersiz dar değere (tipik olarak PK) göre oluşturmaktır.

Kişi Kimliğinizin değişmeyeceğini varsayıyorum, bu nedenle Güncellemeler burada devreye girmez. Ancak Kişi Kimliği 1 2 3 3 4 5 6 7 8 8 olan birkaç satırın anlık görüntüsünü düşünün

Şimdi 3 kişilik Kişi Kimliği için 20 yeni satır ekleyin. İlk olarak, bu benzersiz bir anahtar olmadığından, sunucu değerinize (perde arkasına) onu benzersiz kılmak için fazladan bayt ekler (bu da fazladan alan ekler) ve ardından bunlar ikamet edecekler değiştirilmelidir. Bunu, eklerin sonunda gerçekleştiği yere otomatik artan bir PK eklemekle karşılaştırın. Teknik olmayan açıklama muhtemelen şuna inecektir: Tablonun sonunda doğal olarak daha yüksek değerler ilerliyorsa, öğelerinizi eklerken o konumdaki mevcut öğelerin konumunu yeniden işlerken yapılacak daha az 'yaprak karıştırma' işi vardır.

Şimdi, Eklemeler ile ilgili sorun yaşıyorsanız, büyük olasılıkla aynı (veya benzer) bir dizi Kişi Kimliği değerini aynı anda ekliyorsunuz, bu da bu ekstra çalışmaya tablonun çeşitli yerlerinde neden oluyor ve parçalanma sizi öldürüyor. Durumunuzda kümelenen PK'ye geçmenin dezavantajı, bugün Kişi Kimliklerinde tablo geneline yayılmış değer olarak farklılık gösteren ekleme sorunları yaşıyorsanız, kümelenmiş dizininizi PK'ye geçirirseniz ve tüm ekler artık bir o zaman probleminiz artan çekişme konsantrasyonu nedeniyle daha da kötüleşebilir. (Diğer taraftan, eğer ekleriniz bugün her yere dağılmamışsa, ancak hepsi tipik olarak benzer alanlarda toplanmışsa, o zaman, kümelenmiş dizini PersonId'den PK'nize çevirerek probleminiz büyük olasılıkla hafifleyecektir, çünkü parçalanma.)

Performans problemleriniz benzersiz durumunuza göre analiz edilmeli ve bu tür yanıtları yalnızca genel kılavuzlar olarak almalıdır. Yapabileceğiniz en iyi şey, sorunlarınızın tam olarak nerede olduğunu doğrulayabilecek bir DBA'ya güvenmektir. Basit bir dizin ayarlamasının ötesinde olabilecek kaynak çekişmesi sorunlarınız var gibi görünüyor. Bu, çok daha büyük bir sorunun belirtisi olabilir. (Muhtemelen tasarım sorunları ... aksi takdirde kaynak sınırlamaları.)

Her durumda, iyi şanslar!


5

Bazı yazarlar , aralık sorgularına fayda sağlayacak bir alternatif varsa CI, bir identitysütunun "boşa harcanmamasını" önermektedir .

MSDN Kümelenmiş Dizin Tasarım Yönergelerinden , anahtar aşağıdaki kriterlere göre seçilmelidir

  1. Sık kullanılan sorgular için kullanılabilir.
  2. Yüksek derecede benzersizlik sağlayın.
  3. Aralık sorgularında kullanılabilir.

Sizin CourtOrderIDkolon karşılar 2. Sizin PersonIdkarşılayan 1ve 3. Çoğu satır uniqueifieryine de eklenenle sonuçlanacağından, onu benzersiz olarak ilan edebilir ve PersonId,CourtOrderIDaynı genişlikte olacağı için kullanabilirsiniz , ancak kümelenmiş indeks anahtarı satır bulucu olarak tüm NCI'lere eklendiğinden daha kullanışlı olur ve bu izin verir daha fazla sorguyu kapsayacak şekilde.

PersonId,CourtOrderIDCI olarak kullanmanın ana sorunu , mantıksal parçalanmanın büyük olasılıkla ortaya çıkmasıdır (ve bu özellikle yardım etmeye çalıştığınız aralık sorgularını etkiler), bu nedenle doldurma faktörünü ve parçalama düzeylerini izlemeniz ve dizin bakımını daha sık gerçekleştirmeniz gerekir.


3

Aşağıdaki bağlantıda açıklanmıştır: https://msdn.microsoft.com/en-us/ms190457.aspx

Kümelenmiş

  • Kümelenmiş dizinler , anahtar değerlerine göre tablo veya görünümdeki veri satırlarını sıralar ve saklar . Bunlar, dizin tanımına dahil edilen sütunlardır. Tablo başına yalnızca bir kümelenmiş dizin olabilir, çünkü veri satırlarının kendisi yalnızca tek bir sırada sıralanabilir.

  • Bir tablodaki veri satırlarının sıralı düzende depolandığı tek zaman, tablonun kümelenmiş bir dizin içerdiği zamandır. Bir tablonun kümelenmiş bir dizini olduğunda, tabloya kümelenmiş tablo denir. Bir tablonun kümelenmiş indeksi yoksa, veri satırları yığın adı verilen sırasız bir yapıda saklanır.

Kümelenmemiş

  • Kümelenmemiş dizinler, veri satırlarından ayrı bir yapıya sahiptir. Kümelenmemiş bir dizin , kümelenmemiş dizin anahtar değerlerini tutar ve her bir anahtar değeri girişi, anahtar değerini içeren veri satırına bir işaretçiye sahiptir. .

  • Kümelenmemiş bir dizindeki bir dizin satırından veri satırına olan işaretçiye satır bulucu denir. Satır bulucunun yapısı, veri sayfalarının bir yığın veya kümelenmiş bir tabloda depolanmasına bağlıdır. Yığın için, satır bulucu satıra bir göstericidir. Kümelenmiş bir tablo için, satır bulucu, kümelenmiş dizin anahtarıdır.

  • Var olan dizin anahtarı limitlerini, 900 bayt ve 16 anahtar sütununu atlamak ve tamamen kapsanan, dizinlenmiş sorguları yürütmek için kümelenmemiş dizinin yaprak düzeyine nonkey sütunlar ekleyebilirsiniz.


-3

Bazı kötü seçimlere sahip bazı db, saklı bir yordama katılır - yalnızca fark dizindir

INDEXES - kümelenmiş ve kümelenmemiş

  891 rows
  10 sec
  NONCLUSTERED 

  OR

  891 rows
  14 sec
  CLUSTERED
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.