Hangi sütunlar genellikle iyi indeksler oluşturur?


100

Bir takip yukarı olarak " Ne indeksleri nedir ve bunları benim veritabanında optimize sorguları nasıl kullanabilirim? " Ben dizinleri hakkında bilgi edinmek için çalışılıyor nerede ne sütunlar iyi indeks adaylardır? Özellikle bir MS SQL veritabanı için mi?

Biraz googling yaptıktan sonra, okuduğum her şey, genel olarak artan ve benzersiz olan sütunların iyi bir dizin oluşturduğunu gösteriyor (MySQL'in auto_increment gibi şeyler), bunu anlıyorum, ancak MS SQL kullanıyorum ve birincil anahtarlar için GUID kullanıyorum, öyle görünüyor bu dizinler GUID sütunlarına fayda sağlamaz ...


Bir "yemek kitabı" na ne dersiniz: mysql.rjweb.org/doc.php/index_cookbook_mysql
Rick James

Yanıtlar:


113

Dizinler, sorgu optimizasyonunda ve sonuçları tablolardan hızlı bir şekilde aramada önemli bir rol oynayabilir. Bu nedenle, hangi sütunların dizine ekleneceğini seçmek en önemli adımdır. İndekslemeyi düşünebileceğimiz iki ana yer vardır: WHERE yan tümcesinde referans verilen sütunlar ve JOIN yan tümcelerinde kullanılan sütunlar. Kısacası, belirli kayıtları aramanız gereken bu tür sütunlar dizinlenmelidir. Diyelim ki, SELECT sorgusunun aşağıdaki gibi dizinleri kullandığı alıcılar adlı bir tablomuz var:

SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

SELECT kısmında "alıcı_kimliği" belirtildiğinden, MySQL onu seçilen satırları sınırlamak için kullanmayacaktır. Bu nedenle, dizine eklemeye çok gerek yoktur. Aşağıdakiler, yukarıdakinden biraz farklı başka bir örnektir:

SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

Yukarıdaki sorgulara göre first_name, last_name sütunları WHERE yan tümcesinde bulundukları için dizine alınabilir. Ayrıca, ülke tablosundaki country_id adlı ek bir alan, JOIN yan tümcesinde yer aldığından indeksleme için düşünülebilir. Dolayısıyla, indeksleme, WHERE yan tümcesi veya bir JOIN yan tümcesindeki her alanda düşünülebilir.

Aşağıdaki liste, tablolarınızda indeksler oluşturmayı düşündüğünüzde her zaman aklınızda bulundurmanız gereken birkaç ipucu da sunar:

  • Yalnızca WHERE ve ORDER BY yan tümcelerinde gerekli olan sütunları dizine ekleyin. Sütunları bolca indekslemek bazı dezavantajlara neden olacaktır.
  • MySQL'in "dizin öneki" veya "çok sütunlu dizin" özelliğinden yararlanmaya çalışın. INDEX (ad, soyad) gibi bir dizin oluşturursanız, INDEX (ad_adı) oluşturmayın. Ancak, tüm arama durumlarında "dizin öneki" veya "çok sütunlu dizin" önerilmez.
  • NULL değerlerin hiçbir zaman depolanmaması için, indekslemeyi düşündüğünüz sütunlar için NOT NULL özniteliğini kullanın.
  • Dizin kullanmayan sorguları günlüğe kaydetmek için --log-long-format seçeneğini kullanın. Bu şekilde bu log dosyasını inceleyebilir ve sorgularınızı buna göre ayarlayabilirsiniz.
  • EXPLAIN ifadesi, MySQL'in bir sorguyu nasıl yürüteceğini ortaya çıkarmanıza yardımcı olur. Tabloların nasıl ve hangi sırayla birleştirildiğini gösterir. Bu, optimize edilmiş sorguların nasıl yazılacağını ve sütunların dizine eklenmesinin gerekip gerekmediğini belirlemek için çok yararlı olabilir.

Güncelleme (23 Şub'15):

Herhangi bir dizin (iyi / kötü), ekleme ve güncelleme süresini artırır.

Dizinlerinize (dizin sayısı ve türü) bağlı olarak sonuç aranır. Arama süreniz indeks nedeniyle artacaksa, bu kötü indekstir.

Muhtemelen herhangi bir kitapta, "Dizin Sayfası" bölüm başlangıç ​​sayfasına, konu sayfa numarasının başlamasına ve ayrıca alt konu başlığına sahip olabilir. Dizin sayfasındaki bazı açıklamalar yardımcı olabilir, ancak daha ayrıntılı dizin kafanızı karıştırabilir veya sizi korkutabilir. Dizinler de hafızaya sahiptir.

Dizin seçimi akıllıca olmalıdır. Tüm sütunların indeks gerektirmediğini unutmayın.


Teşekkür Somnath, Bu yüzden biz kullanımına planlama nerede endeksleri sadece sütunlar için oluşturulmalıdır ima etmez WHERE, JOINSya HAVING?
Muhammad Babar

3
Evet, WHERE, JOINS veya HAVING kullanmayı planladığınız sütunlar için dizin kullanın. Ancak, tüm koşul sütunlarının dizin gerektirmediğini de unutmayın. Bazen koşul sütununun yalnızca bir kez kullanıldığı durumlarda dizine ihtiyaç duymayabilir, oysa diğer koşul sütunu birçok sorguda kullanılır, bu nedenle o sütuna dizin oluşturmayı daha çok tercih edin.
Somnath Muluk

1
Cevap, bir TL; DR bölümüne "WHERE yan tümcesinde atıfta bulunulan sütunlar ve JOIN yan tümcelerinde kullanılan sütunlar" koymaktan fayda sağlayacaktır.
jpmc26

Yani, eğer WHEREcümlenimde, sütununun yalnızca iki değer alabildiği bir alanın değerini kontrol ediyorsam , o zaman o ikili sütunu indekslemem gerektiğini söylüyorsunuz? Bu yanlış görünüyor.
AjaxLeung

@AjaxLeung: Knuth'un "Erken Optimizasyon tüm Kötülüklerin köküdür" sözünü hatırlayın. İkili sütunlarda dizin oluşturabilirsiniz, ancak bunun maliyetine bağlı olmalıdır (ekleme, güncelleme zamanları gibi). İş mantığınız genellikle bu ikili anahtara bağlıysa, ikili sütunun dizine sahip olması gerekebilir.
Somnath Muluk

20

Bazıları burada benzer bir soruyu cevapladı: İyi bir endeksin ne olduğunu nasıl anlarsınız?

Temel olarak, gerçekten verilerinizi nasıl sorgulayacağınıza bağlıdır. Veri kümenizin bir sorguyla ilgili küçük bir alt kümesini hızlı bir şekilde tanımlayan bir dizin istiyorsunuz. Hiçbir zaman tarih damgasına göre sorgulama yapmazsanız, çoğunlukla benzersiz olsa bile bir dizine ihtiyacınız yoktur. Tek yaptığınız belirli bir tarih aralığında meydana gelen olayları almaksa, kesinlikle bir tane istersiniz. Çoğu durumda, cinsiyetle ilgili bir indeks anlamsızdır - ancak tek yaptığınız tüm erkekler hakkında ve ayrı ayrı tüm dişiler hakkında istatistikler almaksa, bir tane oluşturmak için zaman ayırmaya değer olabilir. Sorgu modelinizin ne olacağını ve hangi parametreye erişimin arama alanını en çok daralttığını bulun ve bu sizin en iyi dizininizdir.

Ayrıca, oluşturduğunuz dizinin türünü de göz önünde bulundurun - B-ağaçları çoğu şey için iyidir ve aralık sorgularına izin verir, ancak karma dizinler sizi doğrudan noktaya götürür (ancak aralıklara izin vermeyin). Diğer dizin türlerinin başka artıları ve eksileri vardır.

İyi şanslar!


9

Her şey, tablolar hakkında sormayı beklediğiniz sorgulara bağlıdır. X sütunu için belirli bir değere sahip tüm satırları sorarsanız, dizin kullanılamıyorsa tam bir tablo taraması yapmanız gerekecektir.

Aşağıdaki durumlarda dizinler yararlı olacaktır:

  • Sütun veya sütunların yüksek derecede benzersizliği vardır
  • Sütun için sık sık belirli bir değer veya değerler aralığı aramanız gerekir.

Aşağıdaki durumlarda yararlı olmayacaklar:

  • Tablodaki satırların büyük bir yüzdesini (>% 10-20) seçiyorsunuz
  • Ek alan kullanımı bir sorundur
  • Uç performansını en üst düzeye çıkarmak istiyorsunuz. Bir tablodaki her dizin, veri her değiştiğinde güncellenmeleri gerektiğinden, ekleme ve güncelleme performansını azaltır.

Birincil anahtar sütunları, benzersiz olduklarından ve genellikle satırları aramak için kullanıldığından dizin oluşturma için genellikle harikadır.


Değerin dize içinde herhangi bir yerde olabileceği dize aramaları, bu durumda bu dizini kullanmamasına neden olabilir.
Arthur Thomas

5

Genel olarak (mssql kullanmıyorum, bu yüzden özel olarak yorum yapamam), birincil anahtarlar iyi indeksler oluşturur. Benzersizdirler ve belirtilen bir değere sahip olmaları gerekir. (Ayrıca, birincil anahtarlar o kadar iyi dizinler oluşturur ki, normalde otomatik olarak oluşturulmuş bir dizine sahip olurlar.)

Bir indeks, ikili aramaya (doğrusal aramadan çok daha hızlı olan) izin verecek şekilde sıralanmış sütunun etkili bir kopyasıdır. Veritabanı sistemleri, özellikle veriler basit bir sayıdan daha karmaşıksa, aramayı daha da hızlandırmak için çeşitli hileler kullanabilir.

Benim önerim, başlangıçta herhangi bir dizin kullanmamak ve sorgularınızın profilini çıkarmak olacaktır. Belirli bir sorgu (örneğin, soyadına göre kişileri aramak gibi) çok sık çalıştırılırsa, ilgili öznitelikler ve profil üzerinde yeniden bir dizin oluşturmayı deneyin. Sorgularda gözle görülür bir hızlanma varsa ve ekleme ve güncellemelerde göz ardı edilebilir bir yavaşlama varsa, dizini koruyun.

(Diğer sorunuzda bahsedilen şeyleri tekrar edersem özür dilerim, daha önce karşılaşmamıştım.)


5

Tablodan veri çıkarmak için düzenli olarak kullanılacak herhangi bir sütun indekslenmelidir.

Bu, şunları içerir: yabancı anahtarlar -

select * from tblOrder where status_id=:v_outstanding

açıklayıcı alanlar -

select * from tblCust where Surname like "O'Brian%"

Sütunların benzersiz olması gerekmez. Aslında, istisnaları ararken ikili bir dizinden gerçekten iyi bir performans elde edebilirsiniz.

select * from tblOrder where paidYN='N'

Yabancı anahtarlardan açıkça bahsetmeniz, katılma konusunda benim için işleri gerçekten açıklığa kavuşturdu.
pfabri

3

Gerçekten sorularınıza bağlıdır. Örneğin, neredeyse sadece bir tabloya yazıyorsanız, o zaman en iyisi herhangi bir dizine sahip olmamaktır, sadece yazma işlemini yavaşlatır ve asla kullanılmaz. Başka bir tabloyla birleştirmek için kullandığınız herhangi bir sütun, bir dizin için iyi bir adaydır.

Ayrıca Eksik Dizinler özelliği hakkında bilgi edinin. Veritabanınızda kullanılan gerçek sorguları izler ve hangi dizinlerin performansı iyileştireceğini size söyleyebilir.


3

Bir GUID sütunu, indeksleme için en iyi aday değildir. Dizinler, anlamlı bir sıra verilebilen, yani sıralanan (tam sayı, tarih vb.) Bir veri türüne sahip sütunlara en uygun olanıdır.

Bir sütundaki verilerin genel olarak artması önemli değildir. Sütunda bir dizin oluşturursanız, dizin, tablonuzdaki asıl öğelere, depolanmış sırayla ilgilenmeden (kümelenmemiş bir dizin) başvuran kendi veri yapısını oluşturur. Daha sonra, örneğin, hızlı erişim sağlamak için indeks veri yapınız üzerinde bir ikili arama gerçekleştirilebilir.

Verilerinizi fiziksel olarak yeniden sıralayacak bir "kümelenmiş dizin" oluşturmak da mümkündür. Bununla birlikte, tablo başına bunlardan yalnızca birine sahip olabilirsiniz, oysa birden çok kümelenmemiş dizine sahip olabilirsiniz.


Bu, bu şekilde tamamen doğru değil. Bir GUID sütununda kolayca normal, kümelenmemiş bir dizin oluşturabilirsiniz - neden olmasın? GUID'i kümeleme anahtarı olarak kullanırsanız büyük bir dezavantajı vardır (örn. KÜMELENMİŞ DİZİN için) - o zaman kullanmak felakettir.
marc_s

2

Artan veya azalan sırada sıralanan sayısal veri türleri, birçok nedenden dolayı iyi indekslerdir. İlk olarak, sayıların değerlendirilmesi genellikle dizelerden (varchar, char, nvarchar, vb.) Daha hızlıdır. İkinci olarak, değerleriniz sıralı değilse, dizininizi güncellemek için satırların ve / veya sayfaların karıştırılması gerekebilir. Bu ek yük.

SQL Server 2005 kullanıyorsanız ve benzersiz tanımlayıcılar (kılavuzlar) kullanmaya karar verdiyseniz ve bunların rastgele nitelikte olmasına gerek YOKSA, sıralı benzersiz tanımlayıcı türünü kontrol edin.

Son olarak, kümelenmiş indekslerden bahsediyorsanız, fiziksel verilerin türünden bahsediyorsunuz. Kümelenmiş dizininiz olarak bir dizeniz varsa, bu çirkinleşebilir.


1

Genel kural, WHERE, ORDER BY ve GROUP BY yan tümcelerinde çok kullanılan veya birleştirmelerde sıkça kullanılan gibi görünen sütunlardı. Birincil Anahtar DEĞİL, dizinlerden bahsettiğimi unutmayın

'Vanilya benzeri' bir cevap vermemek, ancak bu gerçekten verilere nasıl eriştiğinize bağlı


1

Birincil anahtarınız her zaman bir dizin olmalıdır. (Aslında MS SQL tarafından otomatik olarak indekslenmemiş olsaydı şaşırırdım.) Ayrıca sütunları size SELECTveya ORDERsık sık indekslemelisiniz ; amaçları hem tek bir değerin hızlı aranması hem de daha hızlı sıralamadır.

tooPek çok sütunun indekslenmesindeki tek gerçek tehlike, indekslerin de güncellenmesi gerektiğinden, büyük tablolardaki satır değişikliklerini yavaşlatmaktır. Neyi dizine ekleyeceğinizden gerçekten emin değilseniz, en yavaş sorgularınızı zamanlayın, en sık hangi sütunların kullanıldığına bakın ve bunları dizine ekleyin. Sonra ne kadar hızlı olduklarını görün.


0

Bir GUID kullanıyorsanız, daha da hızlı olmalıdır. Kayıtlara sahip olduğunuzu varsayalım

  1. 100
  2. 200
  3. 3000
  4. ....

Bir indeksiniz varsa (ikili arama, aradığınız kaydın fiziksel konumunu O (lg n) zamanında, sıralı olarak O (n) zamanda aramak yerine bulabilirsiniz. Bunun nedeni, hangi kayıtlara sahip olduğunuzu bilmemenizdir. senin masanda.


0

En iyi dizin, tablonun içeriğine ve neyi başarmaya çalıştığınıza bağlıdır.

Örnek bir Üye Sosyal Güvenlik Numarasının Birincil Anahtarına sahip bir üye veritabanı. SS'yi seçiyoruz çünkü uygulama önceliği bireye bu şekilde atıfta bulunuyor, ancak siz de üyelerin adını ve soyadını kullanacak bir arama işlevi oluşturmak istiyorsunuz. Daha sonra bu iki alan üzerinde bir dizin oluşturmanızı öneririm.

Öncelikle hangi verileri sorgulayacağınızı bulmalı ve ardından hangi verilerin indekslenmesine ihtiyacınız olduğuna karar vermelisiniz.

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.