Kompozit endeks ilk alandaki sorgular için de iyi midir?


86

I alanları bir tablo var diyelim Ave B. A+ Üzerinde düzenli sorgulamalar yapıyorum B, böylece üzerinde bileşik bir dizin oluşturdum (A,B). Ancak sorgular yalnızca Abileşik dizin tarafından tam olarak optimize edilebilir mi?

Ayrıca, üzerinde bir dizin oluşturdum A, ancak Postgres hala yalnızca sorgular için bileşik dizini kullanıyor A. Önceki cevap olumluysa, sanırım bunun önemi yok, ancak tek bir Adizin varsa neden varsayılan olarak bileşik dizini seçiyor?


Bunun için küçük bir test yapmaya çalıştım. Bununla birlikte, benim durumumda, iki sütunlu indeks yalnızca ilk sütunun oluşturduğu alakasız olan tek sütunlu sütunu düşürdüğümde kullanıldı. İlk önce iki sütun indeksini oluşturduysam, ilk planın bir bitmap yığın taraması kullanması ilginçtir. Bir sütunlu dizini oluşturduysam, sorguyu çalıştırın (kullanılmış dizin taraması) ve yeni oluşturulan dizini bıraktıysam, iki sütunlu dizini içeren plan dizin taramasına geçti. SQLFiddle'daki
dezso,

@dezso İlginç. Her sorgu için maliyetler nerede?
Luciano

Bitmap endeksi tarama maliyeti: 107.98, 43 ms yürütme süresi. Dizin taraması bir sütun: maliyet 8.69, iki sütun: 43.69. Uygulama zamanları önemli ölçüde farklı değildir (dalgalanma, ikisi arasındaki farktan büyüktür).
dezso

@ Luciano explain analyzeve sorgu metnini gösterebilir misiniz ?
Craig Ringer

Yanıtlar:


88

Bu kesinlikle. Bu konuyla ilgili ayrıntılı olarak şunları tartıştık:

Boşluk, MAXALIGN64-bit işletim sistemindeki tipik olarak 8 bayt veya 32-bit işletim sistemindeki (çok daha az yaygın) 4 bayt olan katları olarak ayrılır . Emin değilseniz kontrol edin pg_controldata. Ayrıca, dizinlenmiş sütunların veri türlerine (bazıları hizalama dolgusu gerektirir) ve gerçek içeriğe de bağlıdır.

Örneğin, iki integersütun (her biri 4 bayt) üzerindeki bir dizin tipik olarak, bir diğerindeki 4 dizin kadar hizalama dolgusunda kaybedilen bir dizin kadar büyük olur.

Böyle bir durumda sorgu planlayıcısının bir dizini kullanması için bir dezavantajı yoktur (a,b)- sadece bir dizine kıyasla (a). Ve genellikle aynı endeksi kullanmak için birden fazla sorgu olması tercih edilir. Paylaşıldığında, onun (veya bazı bölümlerinin) (hızlı) önbellekte kalma şansı artar.

Zaten bir dizin üzerinde muhafaza ederse (a,b), o zaman duygusu sadece başka bir dizin oluşturmak için yapmaz (a)o sürece - esasen daha küçük. Aynı değil için de geçerlidir (b,a)vs. (a). Daha fazla bilgi için ilk satırdaki bağlantıyı izleyin.

Bunun tersine bir ek endekse ihtiyacınız olduğunda, ters yönden gelirseniz (a,b), mevcut bir endeksi sadece (a)- eğer mümkünse bırakmayı düşünün . Genellikle bu bir PK veya UNIQUEkısıtlamanın endeksi olduğundan mümkün değildir . Postgres 11’den bu yana, sadece cümlesiyle sadece bkısıtlama tanımına ekleme yapmaktan kurtulabilirsiniz INCLUDE. Kılavuzdaki detaylar.

Veya(b,a) sadece bek olarak sorguları da kapsayacak şekilde yeni dizini yaratın . Sadece eşitlik koşulları için btree endekslerindeki indeks ifadelerinin sırası önemli değildir. Ancak, aralık koşullarını içerdiğinde yapar. Görmek:

Yalnızca bir dizine ek sütunlar eklemenin olası dezavantajları vardır; bu yalnızca hizalama dolgusunda kaybedilen boşluğu kullanıyor olsa da

  • Her ne zaman ilave sütun güncellendiğinde, endeksin şimdi de güncellenmesi gerekir, bu da işlem yazmak için maliyet ekleyebilir ve daha fazla endeks kabarcığı yaratabilir.
  • Herhangi bir indeks sütunu söz konusuyken, masadaki SICAK güncellemeler (Sadece Yığın Tuple) mümkün değildir .

SICAK güncellemeler hakkında daha fazlası:

Nesne boyutları nasıl ölçülür:


1
Bunu, A sütununda bir Dizine sahipsem ve bir bileşik dizin (A, B) eklemek için bir ihtiyaç ortaya çıkarsa, A dizininin bırakılması gerektiğini söyler misiniz? Bir dizini yeniden kullanmak önbellek verimliliğini arttırır ve (A, B) A'yı tamamen iyileştirirse, A, A'daki ek bir dizin alanı boşa
harcar

1
jvans: Genel olarak doğru - dikkate değer istisnalar ve alternatifler. Bunu ele almak için bir paragraf ekledim.
Erwin Brandstetter

2

Sorunuza göre, A ve B alanında bir tablo var. Sorunuz varsa:

SELECT * FROM [YOUR TBL]
WHERE A='XXXX'

Optimize Edici, Rasgele erişimi ayıklamaktan kaçınmak için Bileşik dizinini seçecek!


-4

Bu durumda, sadece yüklemdeki ilk önce kullanırsanız.

Kompozit anahtarın ilk sütunlarını ve kompozit anahtarın anahtar olmayan sütununu kullanırsanız tarama yapılır.

Kandırmak için bu gibi kestirimleri yapabilir ve daha sonra anahtar olmayan sütunları:

[A, B] dizininiz, [C] - başka bir sütun

Dizini kullanmak için yazdığınız:

SELECT
    A,B,C,D,E
FROM 
    test
WHERE
   A=1
AND
   B=B
AND 
   C=3

... neden tek A dizini mevcutsa, neden varsayılan olarak bileşik dizini seçer?

İndeks sadece, bir veya iki belirti olması durumunda [A] veya [A], [B] durumunda kullanılacaktır. [B], [A] veya [A], [C] sıralarında kullanmaz. İndeksi ek sütun [C] ile kullanabilmek için, [A], [B] ve [C] şeklinde tahminler vererek endeksi uygulamanız gerekir.


2
Tam olarak ne elde edersiniz B=B? Sanırım hiçbir şey elde edemezsiniz, bu yüzden bu sadece optimizer tarafından göz ardı edildiğine dair hiçbir kanıt bulunmadığını oyluyorum
Jack Douglas

2
B=Betkili olarak B IS NOT NULLçağrılmayan gibi görünüyor. Bir dizin kullanmak kesinlikle gerekli değildir (a,b).
Erwin Brandstetter
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.