Çok önemli bir soru olduğu için bu çok güzel bir soru. Bu çok büyük bir konudur ve size göstereceğim şey basitleştiricidir, böylece temel kavramları anlayabilirsiniz.
Öncelikle kümelenmiş indeksi gördüğünüzde tabloyu düşünün . Bir tablo kümelenmiş bir dizin içermiyorsa SQL sunucusunda bir öbektir. Masada kümelenmiş bir dizin oluşturmak aslında masayı b-ağacı tipi bir yapıya dönüştürür. Kümelenmiş dizininiz tablonuzdur tablodan ayrı değildir
Neden yalnızca bir kümelenmiş dizine sahip olabileceğinizi merak ettiniz mi? İki kümelenmiş indeksimiz olsaydı, tablonun iki kopyasına ihtiyacımız olurdu. Sonuçta verileri içerir.
Bunu basit bir örnek kullanarak açıklamaya çalışacağım.
NOT: Bu örnekte tabloyu oluşturdum ve 3 milyondan fazla rastgele girdiyle doldurdum. Ardından asıl sorguları yürüttü ve yürütme planlarını buraya yapıştırın.
Gerçekten kavramanız gereken şey, O gösterimi veya operasyonel verimliliktir . Aşağıdaki tabloya sahip olduğunuzu varsayalım.
CREATE TABLE [dbo].[Customer](
[CustomerID] [int] IDENTITY(1,1) NOT NULL,
[CustomerName] [varchar](100) NOT NULL,
[CustomerSurname] [varchar](100) NOT NULL,
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED
(
[CustomerID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF
, IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
İşte burada MüşteriNo kümelenmiş bir anahtarla temel bir tablomuz var (Birincil anahtar varsayılan olarak kümelenmiştir). Böylece tablo, birincil müşteri koduna göre düzenlenir / sıralanır. Orta seviyeler MüşteriNo değerleri içerecektir. Veri sayfaları tüm satırı içerecek, böylece tablo satırı olacaktır.
Ayrıca, MüşteriAdı alanında kümelenmemiş bir dizin de oluşturacağız. Aşağıdaki kod yapacak.
CREATE NONCLUSTERED INDEX [ix_Customer_CustomerName] ON [dbo].[Customer]
(
[CustomerName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF
, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF
, DROP_EXISTING = OFF, ONLINE = OFF
, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
Dolayısıyla bu endekste veri sayfaları / yaprak seviyesi düğümlerinde kümelenmiş endekste ara seviyelere bir gösterici bulacaksınız. Dizin, MüşteriAdı alanı çevresinde düzenlenir / sıralanır. Böylece orta seviye MüşteriAdı değerlerini içerir ve yaprak seviyesi imleci içerecektir (bu işaretçi değerleri aslında birincil anahtar değerlerdir veya MüşteriNo sütunu).
Doğru, eğer aşağıdaki sorguyu uygularsak:
SELECT * FROM Customer WHERE CustomerID = 1
SQL muhtemelen kümelenmiş bir dizini bir arama işlemi aracılığıyla okuyacaktır. Arama işlemi, sıralı bir arama olan bir taramadan çok daha verimli olan ikili bir aramadır. Bu yüzden yukarıdaki örneğimizde dizin okunur ve ikili bir arama kullanarak SQL, aradığımız kriterlere uymayan verileri elimine eder. Sorgu planı için ekli ekran görüntüsüne bakın.
Dolayısıyla, operasyonların sayısı veya arama işlemi için O Notasyonu aşağıdaki gibidir:
- Aranan değeri ara düzeydeki değerlerle karşılaştırarak, kümelenmiş dizinde ikili arama yapın.
- Eşleşen değerleri döndür (kümelenmiş dizinin içindeki tüm verileri içerdiğinden, satırdaki tüm dizinlerden gelen tüm sütunları geri getirebileceğini unutmayın)
Bu yüzden iki işlem. Ancak aşağıdaki sorguyu uyguladıysak:
SELECT * FROM Customer WHERE CustomerName ='John'
SQL şimdi arama yapmak için MüşteriAdı üzerindeki kümelenmemiş dizini kullanacak. Ancak, bu kümelenmemiş bir dizin olduğundan, satırdaki verilerin tümünü içermez.
Bu nedenle SQL, eşleştirilen kayıtları bulmak için ara seviyelerde arama yapacaktır, ardından gerçek verileri almak için kümelenmiş indeks üzerinde başka bir arama yapmak için geri döndürülen değerleri kullanarak arama yapacaktır. Bu kafa karıştırıcı sesler biliyorum ama okudum ve hepsi netleşecek.
Kümelenmemiş dizinimiz yalnızca MüşteriAdı alanını (ara düğümlerde depolanan dizinli alan değerleri) ve Müşteri Kimliği olan verinin göstergesini içerdiğinden, endeksin Müşteri Soyadı kaydı yoktur. Müşteri Soyadı kümelenmiş dizin veya tablodan alınmalıdır.
Bu sorguyu çalıştırırken aşağıdaki yürütme planını alıyorum:
Yukarıdaki ekran görüntüsünde dikkat etmeniz gereken iki önemli nokta var.
- SQL eksik bir dizine sahip olduğumu söylüyor (yeşil metin). SQL, CustomerName üzerinde CustomerID ve CustomerSurname içeren bir dizin oluşturmamı öneriyor.
- Ayrıca, sorgu zamanının% 99'unun birincil anahtar dizini / kümelenmiş dizinde bir anahtar araması yapmak için harcandığını da göreceksiniz.
SQL neden bu adı MüşteriName'de öneriyor? Endeks yalnızca MüşteriNo içerdiğinden ve MüşteriName SQL hala tablo / kümelenmiş endekslerden Müşteri soyadını bulmak zorunda.
Dizini yarattığımızda ve CustomerSurname sütununu dizine eklersek, SQL yalnızca kümelenmemiş dizini okuyarak tüm sorguyu karşılayabilir. Bu yüzden SQL kümelenmemiş dizinimi değiştirmemi öneriyor.
Burada, kümelenmiş anahtardan CustomerSurname sütununu almak için SQL'in yapması gereken ekstra işlemi görebilirsiniz.
Böylece işlem sayısı aşağıdaki gibidir:
- Aranan değeri ara düzeydeki değerlerle karşılaştırarak, kümelenmemiş dizinde ikili arama yapın
- Eşleşen düğümler için kümelenmiş dizindeki veriler için işaretçiyi içerecek yaprak düzeyi düğümünü okuyun (yaprak düzeyi düğümleri bu arada birincil anahtar değerlerini içerecektir).
- Dönen her değer için, burada satır değerlerini almak için kümelenmiş dizinde (tablo) bir okuma yapın, Müşteri Soyadını okurduk.
- Eşleşen satırları döndür
Bu değerleri çıkarmak için 4 işlemdir. Kümelenmiş dizini okumakla karşılaştırıldığında gereken işlemlerin iki katı. Kümelenmiş dizininizin tüm verileri içerdiği için en güçlü dizininiz olduğunu gösterin.
Bu yüzden sadece son bir noktayı netleştirmek için. Neden kümelenmemiş dizindeki işaretçinin birincil anahtar değeri olduğunu söylüyorum? Kümelenmemiş dizinin yaprak düzeyi düğümlerinin, sorgumu değiştirdiğim birincil anahtar değerini içerdiğini göstermek için:
SELECT CustomerID
FROM Customer
WHERE CustomerName='Jane'
Bu sorguda SQL, Müşteri Kimliği'ni kümelenmemiş dizinden okuyabilir. Kümelenmiş dizinde bir arama yapmak gerekmez. Bu, buna benzeyen yürütme planında görebilirsiniz.
Bu sorgu ve önceki sorgu arasındaki fark dikkat edin. Arama yok. SQL, kümelenmemiş dizindeki tüm verileri bulabilir
Umarım kümelenmiş dizinin tablo olduğunu ve kümelenmemiş dizinlerin tüm verileri içermediğini anlamaya başlayabilirsiniz. Dizin oluşturma, ikili aramaların yapılabilmesi nedeniyle seçimleri hızlandıracaktır, ancak yalnızca kümelenmiş dizinler tüm verileri içermektedir. Bu nedenle, kümelenmemiş bir dizinde bir arama neredeyse her zaman kümelenmiş dizinden değerlerin yüklenmesine neden olur. Bu ekstra işlemler, kümelenmemiş dizinleri kümelenmiş bir dizinden daha az verimli hale getirir.
Umarım bu işleri temizler. Bir şey anlam ifade etmiyorsa, lütfen bir yorum gönderin; açıklığa kavuşturmaya çalışacağım. Burada oldukça geç ve beynim biraz düz hissediyor. Kırmızı boğa zamanı.