Çok noktalı virgül indeksi ve performans


31

Çok noktalı bir dizine sahip bir tablom var ve sorgularda maksimum performansı elde etmek için indekslerin uygun şekilde sıralanmasından şüphelerim var.

Senaryo:

  • PostgreSQL 8.4, yaklaşık bir milyon satırlık tablo

  • C1 sütunundaki değerler yaklaşık 100 farklı değere sahip olabilir . Değerlerin eşit dağıldığını varsayabiliriz, bu nedenle olası her değer için yaklaşık 10000 satırımız vardır.

  • Sütun c2 1000 farklı değere sahip olabilir . Her olası değer için 1000 satırımız var.

Veri ararken, koşul her zaman bu iki sütun için değerler içerir, böylece tablo c1 ve c2'yi birleştiren çok noktalı bir dizine sahiptir. Filtrelemek için yalnızca bir sütun kullanarak sorgularınız varsa, çok sütunlu bir dizinde sütunları doğru şekilde sıralamanın önemini okudum . Senaryomuzda durum bu değil.

Sorum şu:

Filtrelerden birinin daha küçük bir veri kümesi seçtiği gerçeği göz önüne alındığında, ilk endeks en seçici olanı ise (daha küçük bir kümeye izin veren) performansı arttırır mıyım? Başvurulan makaledeki grafikleri görene kadar bu soruyu hiç düşünmedim:

görüntü tanımını buraya girin

Multicolumn indeksleri hakkında referans alınan makaleden alınan görüntü .

Sorgular, filtreleme için iki sütundaki değerleri kullanır. Filtreleme için yalnızca bir sütun kullanarak hiçbir sorum yok. Hepsi şunlardır: WHERE c1=@ParameterA AND c2=@ParameterB. Bunun gibi durumlar da var:WHERE c1 = "abc" AND c2 LIKE "ab%"

Yanıtlar:


36

Cevap

Web sitesine başvurduğunuzdan use-the-index-luke.combu bölümü dikkate alın:

Dizini Kullan, Luke ›Nerede Madde> Aralıkları Arama› Daha Büyük, Daha Az ve ARASINDAKİ

Durumunuza mükemmel bir şekilde uyan bir örneği var (iki sütunlu dizin, biri eşitlik için test edildi , diğeri aralık için diğeri ), (neden bu güzel dizin grafiklerinin çoğuyla ) @ ypercube'un tavsiyesinin doğru olduğunu ve özetliyor:

Rule of thumb: index for equality first  then for ranges.

Ayrıca sadece bir sütun için iyi mi?

Sadece bir sütunda sorgular için ne yapılacağı açık gibi görünmektedir. Bu ilgili soru altında bununla ilgili daha fazla detay ve kriterler:

İlk önce daha az seçici sütun?

Bunun dışında, her iki sütun için yalnızca eşitlik koşullarınız varsa ?

Önemli değil . Öncelikle, gerçekten önemli olan kendi koşullarını alma olasılığı daha yüksek olan sütunu koyun.

Bu demoyu düşünün veya kendiniz yeniden oluşturun. 100k satır içeren iki sütundan oluşan basit bir tablo oluşturdum. Çok Tek birkaç ile diğeri sürü farklı değerlerin:

CREATE TEMP TABLE t AS
SELECT (random() * 10000)::int AS lots
     , (random() * 4)::int     AS few
FROM generate_series (1, 100000);

DELETE FROM t WHERE random() > 0.9;  -- create some dead tuples, more "real-life"

ANALYZE t;

SELECT count(distinct lots)   -- 9999
     , count(distinct few)    --    5
FROM   t;

Sorgu:

SELECT *
FROM   t
WHERE  lots = 2345
AND    few = 2;

EXPLAIN ANALYZE çıktı (önbelleğe alma efektlerini dışlamak için 10 değerinden biri):

Sıralı Tarama t (maliyet = 0.00..5840.84 satır = 2 genişlik = 8)
               (gerçek zaman = 5.646..15.535 satır = 2 döngü = 1)
  Filtre: ((çok = 2345) VE (çok az = 2))
  Tamponlar: yerel isabet = 443
Toplam çalışma zamanı: 15.557 ms

Dizin ekle, yeniden test et:

CREATE INDEX t_lf_idx ON t(lots, few);
T üzerinde t_lf_idx kullanarak Dizin Tara (maliyet = 0.00..3.76 satırlar = 2 genişlik = 8)
                                (gerçek zaman = 0.008.0.011 satır = 2 döngü = 1)
  Dizin Cond: ((lot = 2345) VE (birkaç = 2))
  Tamponlar: yerel isabet = 4
Toplam çalışma zamanı: 0.027 ms

Başka bir dizin ekle, tekrar test et:

DROP INDEX t_lf_idx;
CREATE INDEX t_fl_idx  ON t(few, lots);
T üzerinde t_fl_idx kullanarak Dizin Tara (maliyet = 0.00..3.74 satırlar = 2 genişlik = 8)
                                (gerçek zaman = 0.007.0.011 satır = 2 döngü = 1)
  Dizin Cond: ((az = 2) VE (çok = 2345))
  Tamponlar: yerel isabet = 4
Toplam çalışma zamanı: 0.027 ms

Bu aynı zamanda dizindeki 3 (veya daha fazla) sütun için de geçerli midir?
19:52

@Hayd: "Bu" nın ne anlama geldiğinden emin değil. Yeni bir soru sorabilirsin . Bağlam için buna her zaman başvurabilirsiniz. (Ve geri bağlantı için buraya bir yorum bırakın.)
Erwin Brandstetter

"Bu" demek istediğim "dizin tanımının sıralanmasında, indeks tanımında 2'den fazla sütun olması önemli değil"
hayd

@Hayd: En önemli nokta: btree endeksi, öncü endeks ifadelerindeki eşitlik koşullarına sahip sorgular için iyidir . Bunlar arasındaki düzen çoğunlukla alakasızdır.
Yoruma

Teşekkürler, tutarlı bir soru yazmaya çalışacağım ve bağlantı kuracağım.
Hayd

11

Söylediğiniz gibi, bu 2 sütunu içeren sorgular, her iki sütunun eşitlik kontrolleriyse, örneğin:

WHERE c1=@ParameterA AND c2=@ParameterB

bununla uğraşma. Herhangi bir fark olacağından şüpheliyim ve eğer bir tane varsa, ihmal edilebilir. Verileriniz ve sunucu ayarlarınızla her zaman elbette test edebilirsiniz. Bir DBMS'nin farklı sürümleri optimizasyon konusunda biraz farklı davranabilir.

Dizinin içindeki sıra, yalnızca bir sütunun kontrolünü veya eşitsizlik koşullarını veya bir sütunda ve diğerinde gruplamayı vb. İçeren diğer sorgular için önemli olacaktır.

İki siparişten birini seçersem, daha az seçici sütunu önce koymayı seçerdim . Sütun içeren bir tablo düşünün yearve month. Bir WHERE year = 2000şart veya a WHERE year BETWEEN 2000 AND 2013veya a ihtiyacınız olması daha olasıdır WHERE (year, month) BETWEEN (1999, 6) AND (2000, 5).

Bu tip bir sorgudan WHERE month = 7 GROUP BY yearemin olmak istenebilir (Temmuz'da doğan insanları bul), fakat daha az sıklıkta olur. Tabii ki tablonuzda depolanan gerçek verilere bağlıdır. Şimdilik bir sipariş seçin, (c1, c2)ve daha sonra her zaman başka bir dizin ekleyebileceğinizi söyleyin (c2, c1).


OP'nin yorumundan sonra güncelleme :

Bunun gibi durumlar da var: WHERE c1 = 'abc' AND c2 LIKE 'ab%'

Bu tür bir sorgu tam olarak c2sütun üzerinde bir aralık koşulu ve bir (c1, c2)indekse ihtiyaç duyarsa. Ayrıca ters tipte sorularınız varsa:

WHERE c2 = 'abc' AND c1 LIKE 'ab%'

o zaman bir (c2, c1)endeks olsaydı iyi olurdu .

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.