Her sorgu türü için ayrı dizinlere ihtiyacım var mı, yoksa bir çok sütunlu dizin çalışacak mı?


22

Ben zaten bu sorunun cevabını biraz biliyorum, ama konuyla ilgili daha fazla bilgiye ihtiyacım varmış gibi hissediyorum.

Temel olarak anladığım kadarıyla, genel olarak konuşursak, herhangi bir zamanda sorguladığınız / sıraladığınız tüm alanları içeren tek bir endeksin yararlı olma olasılığı yoktur, ama bu tür bir şey gördüm. Biri "Bir şeyleri bir dizine koyarsak, veritabanının ihtiyaç duyduğu şeyi bulmak için kullanabilir" diye düşündü, çalışmakta olan bazı sorguların yürütülmesi için bir plan görmedim.

Böyle bir tablo düşünün:

id int pk/uid
name varchar(50)
customerId int (foreign key)
dateCreated datetime

Ben de dahil olmak üzere tek bir endeks görebilirsiniz name, customerIdve dateCreatedalanlar.

Fakat benim anladığım kadarıyla, böyle bir endeks, örneğin:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

Böyle bir sorgu için, daha iyi bir fikrin alanı 'ilk' olacak şekilde customerIdve dateCreatedalanları içeren bir dizin olacağı anlaşılıyor customerId. Bu, verileri, bu sorgunun ihtiyaç duyduğu sırada hızlı bir şekilde bulabileceği şekilde organize edecek bir dizin oluşturacaktır.

Gördüğüm bir diğer şey, belki de ilk sıklıkta, her alandaki bireysel dizinler; böylece, tek her biri üzerinde name, customerIdve dateCreatedalanlar.

İlk örnekten farklı olarak, bu tür bir düzenleme bana bazen en azından kısmen faydalı görünüyor; sorgunun yürütme planı en azından customerIdkayıtları seçmek için dizini kullanıyor olabilir , ancak dizini bu dateCreatedalanları sıralamak için kullanmıyor .


Bunun geniş bir soru olduğunu biliyorum, çünkü belirli bir tablo grubundaki herhangi bir sorgunun özel cevabı genellikle yürütme planının ne yapacağını görmek ve aksi takdirde tablonun / tabloların özelliklerini sorgular ve sorguları içine almaktır. hesap. Ayrıca, bir sorgunun, bunun için belirli bir dizini sağlamanın ek yükünün aksine ne kadar sıklıkla çalıştırılabileceğine bağlı olduğunu da biliyorum.

Fakat sanırım istediğim endeksler için genel bir “başlangıç ​​noktası”, spesifik, sık sorulan sorular ve WHERE veya ORDER BY deyimlerindeki alanlar için özel endekslere sahip olma fikri mi?

Yanıtlar:


27

Örnek sorgunuzun bu dizini kullanmayacağı konusunda haklısınız.

Sorgu planlayıcısı eğer bir dizin kullanmayı düşünecektir:

  • İçerdiği tüm alanlar sorguda belirtilir.
  • Başlangıçtan itibaren bazı alanlara başvurulur.

Sorgu tarafından kullanılmayan bir alanla başlayan dizinleri kullanamaz.

Öyleyse, örneğin:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

aşağıdaki gibi endeksleri dikkate alır:

[customerId]
[customerId], [dateCreated]
[customerId], [dateCreated], [name]

Ama değil:

[name], [customerId], [dateCreated]

Hem bulduysanız [customerId]ve [customerId], [dateCreated], [name]alanlardaki verilerin denge tahminlerine dayanır endeks istatistikleri bağlı olacağını birini diğerine tercih kararını. Eğer [customerId], [dateCreated]tanımlanmışsa, aksine ikame bir ipucu vermediğiniz sürece, diğer ikisini tercih etmeli.

Tecrübelerime göre her alan için tanımlanmış bir endeks görmek de nadir değildir, ancak ender endeks eklemek / güncellemek için gereken ekstra yönetim ve bunları saklamak için gereken ekstra alan boşa harcandığı için bu nadiren idealdir. bunlar asla kullanılamayabilir - ancak DB'niz yazma ağır yükleri görmediği sürece performans aşırı endekslerde bile kötü kokmaz.

Tablo veya indeks taramasından dolayı yavaş olacak sık sorgular için spesifik endeksler genellikle iyi bir fikirdir, ancak bir performans sorununu bir başkasıyla değiş tokuş edebileceğinizden aşırıya kaçmayın. [customerId], [dateCreated]Örneğin, bir dizin olarak tanımlarsanız , sorgu planlayıcısının, yalnızca [customerId]varsa , üzerinde bir dizin kullanacak olan sorgularda bunu kullanabileceğini unutmayın . Kullanım sadece [customerId]bileşik dizini kullanmaktan biraz daha etkili olsa da, bu durum RAM'de alan için rekabet eden iki endekse bir son vermekle azaltılabilir (normal çalışma setinizin tamamı RAM'e kolayca sığabiliyorsa bu ekstra bellek yarışması olmayabilir. sorun).


+1; harika bir bilgi, planlayıcısı özellikle hatırlatma (ı unutmak eğiliminde olan!) olabilir sadece bir sorgu için ondan ilk alan (lar) gerektiğinde zamanlarda bileşik endeksi kullanın.
Andrew Barber,

6

Asıl sorunuzu cevaplamak için, evet, yalnızca tablo değil , sorgular etrafında dizinlerin tasarlanması gerekir . Dizindeki alanların sırası hayati derecede önemlidir. Birden fazla sorgu için en uygun olacak tek bir endeks tasarlamak daha zordur ve değiş tokuş yapmanız gerekecektir.

İkinci noktanızla ilgili olarak, evet, bireysel alanlardaki tek indeks demet can sıkıcı şekilde yaygındır. Bunu her zaman çevremde görüyorum ve geliştirme ekibinin uygun endeksleri tasarlamak için DBA ile birlikte çalışmadığını bana gösteren kırmızı bayrak.

Dizin tasarlama stratejim, dizine eklemektir:

  • NEREDE kullanılan alanlar (seçicilik sırasına göre)
  • SİPARİŞ BY'de kullanılan alanlar
  • Bir örtü endeksi oluşturmak için (gerekirse) diğer alanları ekleyin

Öyleyse, örneğin:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

Büyük olasılıkla (CustomerID, dateCreated) INCLUDE (id, name) üzerine bir dizin tasarlardım. Bu örtü endeksi, sorgunun orijinal tabloyu vurmak zorunda kalmayacağı ve performansı büyük ölçüde arttıracağı anlamına gelir.

Bu örnek olsa da , neredeyse çok basittir. Sadece (MüşteriNo) üzerindeki naif bir endeks neredeyse her zaman iyi bir performans sergileyebilir (her müşterinin sadece tek bir temsilcisi olduğu varsayılarak, masaya yalnızca tek bir yer imi aranması gerekir). Ayrıca , tablodaki diğer sorguların ne olduğuna bağlı olarak, kümelenmiş bir dizinde (MüşteriNo.Kimliği) gerçekten de faydalı olabilir .


"Dizinler, yalnızca tablo değil, sorgular etrafında tasarlanmalı" ve cevabın geri kalanı, örneğin çok basit olduğunu belirtmek gibi.
Andrew Barber,
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.