BTree
ปัญหาของฉันอยู่ที่นี่ว่าดัชนี BTree จะมีขนาดใหญ่เนื่องจากมันจะเก็บค่าที่ซ้ำกัน (มันมีเช่นกันเพราะมันไม่สามารถถือว่าตารางที่มีการจัดเรียงทางกายภาพ) ถ้า BTree มีขนาดใหญ่ฉันจะต้องอ่านทั้งดัชนีและส่วนต่าง ๆ ของตารางที่ดัชนีชี้เกินไป ...
ไม่จำเป็น - การมีดัชนี btree ที่'ครอบคลุม'จะเป็นเวลาที่เร็วที่สุดในการอ่านและถ้านั่นคือทั้งหมดที่คุณต้องการ (เช่นถ้าคุณสามารถจ่ายพื้นที่เก็บข้อมูลเพิ่มเติม) นั่นคือทางออกที่ดีที่สุดของคุณ
Brin
ความเข้าใจของฉันคือฉันสามารถมีดัชนีขนาดเล็กที่นี่ที่ค่าใช้จ่ายในการอ่านหน้าไร้ประโยชน์ การใช้วิธีการเล็ก ๆpages_per_range
นั้นดัชนีนั้นใหญ่กว่า (ซึ่งเป็นปัญหาของ BRIN เนื่องจากฉันต้องอ่านดัชนีทั้งหมด) โดยมีวิธีการขนาดใหญ่pages_per_range
ที่ฉันจะอ่านหน้าไร้ประโยชน์มากมาย
ถ้าคุณไม่สามารถจ่ายค่าใช้จ่ายในการจัดเก็บข้อมูลของดัชนี btree ครอบคลุม Brin เหมาะสำหรับคุณเพราะคุณมีการจัดกลุ่มอยู่ในสถานที่ (ซึ่งเป็นสิ่งสำคัญสำหรับ Brin ที่จะเป็นประโยชน์) ดัชนี Brin มีขนาดเล็กpages_per_range
เพื่อให้ทุกหน้ามีแนวโน้มที่จะอยู่ในหน่วยความจำถ้าคุณเลือกค่าที่เหมาะสม
มีสูตรวิเศษในการค้นหามูลค่าที่ดีของ pages_per_range ที่คำนึงถึงการแลกเปลี่ยนที่ไม่ชอบเหล่านั้นหรือไม่?
ไม่มีสูตรเวทมนต์ แต่เริ่มต้นด้วยขนาดที่pages_per_range
น้อยกว่าขนาดเฉลี่ย (เป็นหน้า) ที่ครอบครองโดยa
ค่าเฉลี่ย คุณอาจพยายามย่อ: (จำนวนหน้า BRIN ที่สแกน) + (จำนวนหน้าฮีปที่สแกน) สำหรับการสืบค้นทั่วไป ค้นหาHeap Blocks: lossy=n
ในแผนการดำเนินการpages_per_range=1
และเปรียบเทียบกับค่าอื่น ๆpages_per_range
เช่นดูจำนวนบล็อกฮีปที่ไม่จำเป็นที่ถูกสแกน
GIN / สรุปสาระสำคัญ
ไม่แน่ใจว่าสิ่งเหล่านี้มีความเกี่ยวข้องที่นี่เนื่องจากส่วนใหญ่จะใช้สำหรับการค้นหาข้อความแบบเต็ม แต่ฉันก็ได้ยินว่าพวกเขาจัดการกับคีย์ที่ซ้ำกันได้ดี a GIN
/ GiST
index จะช่วยที่นี่หรือไม่
GIN อาจมีมูลค่าการพิจารณา แต่อาจไม่ใช่ GiST - แต่ถ้าการจัดกลุ่มตามธรรมชาติดีจริงๆ BRIN น่าจะเป็นทางออกที่ดีกว่า
นี่คือการเปรียบเทียบตัวอย่างระหว่างประเภทดัชนีที่แตกต่างกันสำหรับข้อมูลจำลองเล็กน้อยเช่นคุณ:
ตารางและดัชนี:
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;
ขนาดความสัมพันธ์:
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;
ชื่อ | ขนาด | หน้า | แถว / หน้า
: ----------------- | : ------ | ----: | --------:
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:
explain analyze select sum(b) from foo where a='a';
| QUERY PLAN |
| : ------------------------------------------------- -------------------------------------------------- ------------------------------------------- |
| ผลรวม (ราคา = 3282.57..3282.58 แถว = 1 ความกว้าง = 8) (เวลาจริง = 45.942..45.942 แถว = 1 ลูป = 1)
| -> ดัชนีสแกนอย่างเดียวโดยใช้ foo_btree_covering บน foo (ราคา = 0.43 ..3017.80 แถว = 105907 กว้าง = 4) (เวลาจริง = 0.038..27.286 แถว = 100000 ลูป = 1) |
| ดัชนี Cond: (a = 'a' :: text) |
| กองการดึงข้อมูล: 0 |
| เวลาในการวางแผน: 0.099 ms |
| เวลาดำเนินการ: 45.968 ms |
btree ธรรมดา:
drop index foo_btree_covering;
explain analyze select sum(b) from foo where a='a';
| QUERY PLAN |
| : ------------------------------------------------- -------------------------------------------------- ----------------------------- |
| ผลรวม (ราคา = 4064.57..4064.58 แถว = 1 ความกว้าง = 8) (เวลาจริง = 54.242..54.242 แถว = 1 ลูป = 1)
| -> การสแกนดัชนีโดยใช้ foo_btree บน foo (ราคา = 0.43..3799.80 แถว = ความกว้าง 105907 = 4) (เวลาจริง = 0.037..33.084 แถว = 100000 ลูป = 1) |
| ดัชนี Cond: (a = 'a' :: text) |
| เวลาในการวางแผน: 0.135 ms |
| เวลาดำเนินการ: 54.280 ms |
BRIN pages_per_range = 4:
drop index foo_btree;
explain analyze select sum(b) from foo where a='a';
| QUERY PLAN |
| : ------------------------------------------------- -------------------------------------------------- ----------------------------- |
| ผลรวม (ราคา = 21595.38..21595.39 แถว = 1 ความกว้าง = 8) (เวลาจริง = 52.455..52.455 แถว = 1 ลูป = 1) |
| -> Bitmap Heap สแกนบน foo (ราคา = 888.78..21330.61 แถว = 105907 width = 4) (เวลาจริง = 2.738..31.967 แถว = 100000 ลูป = 1) |
| ตรวจสอบอีกครั้ง Cond: (a = 'a' :: text) |
| แถวถูกลบโดยดัชนีรั้งอีกครั้ง: 96 |
| บล็อกฮีป: lossy = 736 |
| -> ดัชนีบิตแมปสแกน foo_brin_4 (ราคา = 0.00..862.30 แถว = 105907 กว้าง = 0) (เวลาจริง = 2.720..2.720 แถว = 7360 ลูป = 1) |
| ดัชนี Cond: (a = 'a' :: text) |
| เวลาในการวางแผน: 0.101 ms |
| เวลาดำเนินการ: 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 |
| : ------------------------------------------------- -------------------------------------------------- ----------------------------- |
| ผลรวม (ราคา = 21659.38..21659.39 แถว = 1 ความกว้าง = 8) (เวลาจริง = 53.971..53.971 แถว = 1 ลูป = 1)
| -> Bitmap Heap สแกนบน foo (ราคา = 952.78..21394.61 แถว = 105907 width = 4) (เวลาจริง = 5.286..33.492 แถว = 100000 ลูป = 1) |
| ตรวจสอบอีกครั้ง Cond: (a = 'a' :: text) |
| แถวถูกลบโดยดัชนีรั้งอีกครั้ง: 96 |
| บล็อกฮีป: lossy = 736 |
| -> ดัชนีบิตแมปสแกน foo_brin_2 (ราคา = 0.00..926.30 แถว = 105907 กว้าง = 0) (เวลาจริง = 5.275..5.275 แถว = 7360 ลูป = 1) |
| ดัชนี Cond: (a = 'a' :: text) |
| เวลาในการวางแผน: 0.095 ms |
| เวลาดำเนินการ: 54.016 ms |
จิน:
drop index foo_brin_2;
explain analyze select sum(b) from foo where a='a';
| QUERY PLAN |
| : ------------------------------------------------- -------------------------------------------------- ------------------------------ |
| ผลรวม (ราคา = 21687.38..21687.39 แถว = 1 ความกว้าง = 8) (เวลาจริง = 55.331..55.331 แถว = 1 ลูป = 1) |
| -> Bitmap Heap สแกนบน foo (ราคา = 980.78..21422.61 แถว = 105907 width = 4) (เวลาจริง = 12.377..33.956 แถว = 100000 ลูป = 1) |
| ตรวจสอบอีกครั้ง Cond: (a = 'a' :: text) |
| บล็อกฮีป: แน่นอน = 736 |
| -> ดัชนีบิตแมปสแกน foo_gin (ราคา = 0.00..954.30 แถว = ความกว้าง 1,0907 = 0) (เวลาจริง = 12.271 ..12.271 แถว = 100000 ลูป = 1) |
| ดัชนี Cond: (a = 'a' :: text) |
| เวลาในการวางแผน: 0.118 ms |
| เวลาดำเนินการ: 55.366 ms |
dbfiddle ที่นี่