B-ağacı
Burada benim sorunum BTree endeksi yinelenen değerleri depolamak afaict büyük olacaktır (tablonun fiziksel olarak sıralandığı varsayılamıyor çünkü). BTree büyükse, hem indeksi hem de tablonun dizin işaret ettiği bölümlerini okumak zorunda kalıyorum ...
Mutlaka değil - 'kapsayan' bir btree indeksine sahip olmak en hızlı okuma süresi olacaktır ve eğer istediğiniz her şey buysa (yani ekstra depolama alanı varsa), o zaman en iyi bahistir.
BRIN
Anladığım kadarıyla, işe yaramaz sayfaları okumak pahasına burada küçük bir dizin oluşturabilirim. Küçük bir pages_per_range
dizin kullanmak daha büyük anlamına gelir (tüm dizini okumak gerekir çünkü BRIN ile ilgili bir sorun), pages_per_range
çok sayıda işe yaramaz sayfa okuyacağım büyük bir araç.
Bir kaplama btree indeksinin depolama yükünü karşılayamıyorsanız, BRIN sizin için idealdir, çünkü zaten yerinde kümelemeye sahipsiniz (bu BRIN'nin yararlı olması için çok önemlidir ). BRIN dizinleri küçük olduğundan , uygun bir değer seçerseniz tüm sayfaların bellekte olması muhtemeldir pages_per_range
.
Bu değiş tokuşları hesaba katan iyi bir pages_per_range değeri bulmak için sihirli bir formül var mı?
Sihirli formül yok, ancak ortalama değerin işgal ettiği ortalama boyuttan (sayfalarda) pages_per_range
biraz daha az ile başlayın a
. Muhtemelen simge durumuna küçültmeye çalışıyorsunuz: (taranan BRIN sayfa sayısı) + (taranan yığın sayfa sayısı). Heap Blocks: lossy=n
Yürütme planını arayın pages_per_range=1
ve diğer değerlerle karşılaştırın pages_per_range
- yani kaç gereksiz yığın bloğunun tarandığını görün.
CİN / GiST
Çoğunlukla tam metin araması için kullanıldıklarından, bunların alakalı olduğundan emin değilim, ancak yinelenen anahtarlarla uğraşmada iyi olduklarını duyuyorum. Misiniz ya bir GIN
/ GiST
burada indeks yardım?
GIN düşünmeye değer olabilir, ancak muhtemelen GiST değil - ancak doğal kümelenme gerçekten iyi ise, BRIN muhtemelen daha iyi bir bahis olacaktır.
İşte sizinki gibi kukla veriler için farklı dizin türleri arasında örnek bir karşılaştırma:
tablo ve dizinler:
create table foo(a,b,c) as
select *, lpad('',20)
from (select chr(g) a from generate_series(97,122) g) a
cross join (select generate_series(1,100000) b) b
order by a;
create index foo_btree_covering on foo(a,b);
create index foo_btree on foo(a);
create index foo_gin on foo using gin(a);
create index foo_brin_2 on foo using brin(a) with (pages_per_range=2);
create index foo_brin_4 on foo using brin(a) with (pages_per_range=4);
vacuum analyze;
ilişki boyutları:
select relname "name", pg_size_pretty(siz) "size", siz/8192 pages, (select count(*) from foo)*8192/siz "rows/page"
from( select relname, pg_relation_size(C.oid) siz
from pg_class c join pg_namespace n on n.oid = c.relnamespace
where nspname = current_schema ) z;
adı | boyut | sayfalar | satır / sayfa
: ----------------- | : ------ | ----: | --------:
foo | 149 MB | 19118 | 135
foo_btree_covering | 56 MB | 7132 | 364
foo_btree | 56 MB | 7132 | 364
foo_gin | 2928 kB | 366 | 7103
foo_brin_2 | 264 kB | 33 | 78787
foo_brin_4 | 136 kB | 17 | 152941
btree kapsayan:
explain analyze select sum(b) from foo where a='a';
| QUERY PLAN |
| : ------------------------------------------------- -------------------------------------------------- ------------------------------------------- |
| Toplam (maliyet = 3282.57..3282.58 satır = 1 genişlik = 8) (gerçek zaman = 45.942..45.942 satır = 1 döngü = 1) |
| -> Sadece Dizin foo üzerinde foo_btree_covering kullanarak tarama (maliyet = 0.43..3017.80 satır = 105907 genişlik = 4) (gerçek zaman = 0.038..27.286 satır = 100000 döngü = 1) |
| Endeks Koşulu: (a = 'a' :: metin) |
| Öbek Getiriyor: 0 |
| Planlama süresi: 0.099 ms |
| Yürütme süresi: 45.968 ms |
düz ağaç
drop index foo_btree_covering;
explain analyze select sum(b) from foo where a='a';
| QUERY PLAN |
| : ------------------------------------------------- -------------------------------------------------- ----------------------------- |
| Toplam (maliyet = 4064.57..4064.58 satır = 1 genişlik = 8) (gerçek zaman = 54.242..54.242 satır = 1 döngü = 1) |
| -> Foo üzerinde foo_btree kullanarak Dizin Tarama (maliyet = 0.43..3799.80 satır = 105907 genişlik = 4) (gerçek zaman = 0.037..33.084 satır = 100000 döngü = 1) |
| Endeks Koşulu: (a = 'a' :: metin) |
| Planlama süresi: 0.135 ms |
| Yürütme süresi: 54.280 ms |
BRIN pages_per_range = 4:
drop index foo_btree;
explain analyze select sum(b) from foo where a='a';
| QUERY PLAN |
| : ------------------------------------------------- -------------------------------------------------- ----------------------------- |
| Toplam (maliyet = 21595.38..21595.39 satır = 1 genişlik = 8) (gerçek zaman = 52.455..52.455 satır = 1 döngü = 1) |
| -> Bitmap Yığın Foo'da tarama (maliyet = 888.78..21330.61 satır = 105907 genişlik = 4) (gerçek zaman = 2.738..31.967 satır = 100000 döngü = 1) |
| Cond'u tekrar kontrol et: (a = 'a' :: metin) |
| Index Recheck tarafından kaldırılan satırlar: 96 |
| Yığın Blokları: kayıplı = 736 |
| -> Bitmap Dizini foo_brin_4 üzerinde tarama (maliyet = 0.00..862.30 satır = 105907 genişlik = 0) (gerçek zaman = 2.720..2.720 satır = 7360 döngü = 1) |
| Endeks Koşulu: (a = 'a' :: metin) |
| Planlama süresi: 0.101 ms |
| Yürütme süresi: 52.501 ms |
BRIN pages_per_range = 2:
drop index foo_brin_4;
explain analyze select sum(b) from foo where a='a';
| QUERY PLAN |
| : ------------------------------------------------- -------------------------------------------------- ----------------------------- |
| Toplam (maliyet = 21659.38..21659.39 satır = 1 genişlik = 8) (gerçek zaman = 53.971..53.971 satır = 1 döngü = 1) |
| -> Bitmap Yığın Foo'da tarama (maliyet = 952.78..21394.61 satır = 105907 genişlik = 4) (gerçek zaman = 5.286..33.492 satır = 100000 döngü = 1) |
| Cond'u tekrar kontrol et: (a = 'a' :: metin) |
| Index Recheck tarafından kaldırılan satırlar: 96 |
| Yığın Blokları: kayıplı = 736 |
| -> Bitmap Dizini foo_brin_2 üzerinde tarama (maliyet = 0.00..926.30 satır = 105907 genişlik = 0) (gerçek zaman = 5.275..5.275 satır = 7360 döngü = 1) |
| Endeks Koşulu: (a = 'a' :: metin) |
| Planlama süresi: 0.095 ms |
| Yürütme süresi: 54.016 ms |
CİN:
drop index foo_brin_2;
explain analyze select sum(b) from foo where a='a';
| QUERY PLAN |
| : ------------------------------------------------- -------------------------------------------------- ------------------------------ |
| Toplam (maliyet = 21687.38..21687.39 satır = 1 genişlik = 8) (gerçek zaman = 55.331..55.331 satır = 1 döngü = 1) |
| -> Bitmap Yığın Foo'da tarama (maliyet = 980.78..21422.61 satır = 105907 genişlik = 4) (gerçek zaman = 12.377..33.956 satır = 100000 döngü = 1) |
| Cond'u tekrar kontrol et: (a = 'a' :: metin) |
| Yığın Blokları: tam = 736 |
| -> Bitmap Dizini foo_gin üzerinde tarama (maliyet = 0.00..954.30 satır = 105907 genişlik = 0) (gerçek zaman = 12.271..12.271 satır = 100000 döngü = 1) |
| Endeks Koşulu: (a = 'a' :: metin) |
| Planlama süresi: 0.118 ms |
| Yürütme süresi: 55,366 ms |
dbfiddle burada