BTree
Vấn đề của tôi ở đây là chỉ số BTree sẽ rất lớn kể từ khi nó sẽ lưu trữ các giá trị trùng lặp (nó cũng vậy, vì nó không thể giả định bảng được sắp xếp vật lý). Nếu BTree rất lớn, cuối cùng tôi cũng phải đọc cả chỉ mục và các phần của bảng mà chỉ mục cũng chỉ ...
Không nhất thiết - Có chỉ số btree là 'bao phủ' sẽ là thời gian đọc nhanh nhất và nếu đó là tất cả những gì bạn muốn (nghĩa là nếu bạn có đủ khả năng lưu trữ thêm), thì đó là cách tốt nhất của bạn.
BRIN
Sự hiểu biết của tôi là tôi có thể có một chỉ số nhỏ ở đây với chi phí đọc các trang vô dụng. Sử dụng một pages_per_range
phương tiện nhỏ có nghĩa là chỉ mục lớn hơn (đó là vấn đề với BRIN vì tôi cần đọc toàn bộ chỉ mục), có một pages_per_range
phương tiện lớn là tôi sẽ đọc rất nhiều trang vô dụng.
Nếu bạn không đủ khả năng lưu trữ chi phí lưu trữ của chỉ số btree, BRIN là lý tưởng cho bạn, vì bạn đã phân cụm sẵn (điều này rất quan trọng đối với BRIN là hữu ích). Các chỉ mục BRIN rất nhỏ , vì vậy tất cả các trang có khả năng nằm trong bộ nhớ nếu bạn chọn một giá trị phù hợp pages_per_range
.
Có một công thức kỳ diệu để tìm ra một giá trị tốt của Pages_per_range có tính đến những sự đánh đổi đó không?
Không có công thức ma thuật, nhưng bắt đầu với pages_per_range
phần nào nhỏ hơn kích thước trung bình (tính theo trang) chiếm a
giá trị trung bình . Có lẽ bạn đang cố gắng giảm thiểu: (số trang BRIN được quét) + (số trang heap được quét) cho một truy vấn thông thường. Tìm kiếm Heap Blocks: lossy=n
trong kế hoạch thực hiện pages_per_range=1
và so sánh với các giá trị khác cho pages_per_range
- tức là xem có bao nhiêu khối heap không cần thiết đang được quét.
GIN / GiST
Không chắc chắn những thứ đó có liên quan ở đây vì chúng chủ yếu được sử dụng cho tìm kiếm toàn văn bản, nhưng tôi cũng nghe rằng chúng rất tốt trong việc xử lý các khóa trùng lặp. Một GIN
/ GiST
chỉ số sẽ giúp ở đây?
GIN có thể đáng để xem xét, nhưng có lẽ không phải là GiST - tuy nhiên nếu phân cụm tự nhiên thực sự tốt, thì BRIN có thể sẽ là một lựa chọn tốt hơn.
Dưới đây là so sánh mẫu giữa các loại chỉ mục khác nhau cho dữ liệu giả giống như của bạn:
bảng và chỉ mục:
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;
kích thước quan hệ:
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;
tên | kích thước | trang | hàng / trang
: ----------------- | : ------ | ----: | --------:
foo | 149 MB | 19118 | 135
foo_btree_covering | 56 MB | 7132 | 364
foo_btree | 56 MB | 7132 | 364
foo_gin | 2928 kB | 365 | 7103
foo_brin_2 | 264 kB | 33 | 78787
foo_brin_4 | 136 kB | 17 | 152941
bao gồm btree:
explain analyze select sum(b) from foo where a='a';
| KẾ HOẠCH NHANH |
| : ------------------------------------------------- -------------------------------------------------- ------------------------------------------- |
| Tổng hợp (chi phí = 3282,57..3282,58 hàng = 1 chiều rộng = 8) (thời gian thực tế = 45.942..45.942 hàng = 1 vòng = 1) |
| -> Chỉ quét chỉ mục bằng cách sử dụng foo_btree_covering trên foo (cost = 0.43..3017.80 hàng = 105907 width = 4) (thời gian thực tế = 0.038..27.286 hàng = 100000 vòng = 1) |
| Chỉ số Cond: (a = 'a' :: text) |
| Tải Heap: 0 |
| Thời gian lập kế hoạch: 0,099 ms |
| Thời gian thực hiện: 45.968 ms |
đồng bằng btree:
drop index foo_btree_covering;
explain analyze select sum(b) from foo where a='a';
| KẾ HOẠCH NHANH |
| : ------------------------------------------------- -------------------------------------------------- ----------------------------- |
| Tổng hợp (chi phí = 4064,57..4064,58 hàng = 1 chiều rộng = 8) (thời gian thực tế = 54.242..54.242 hàng = 1 vòng = 1) |
| -> Quét chỉ mục bằng cách sử dụng foo_btree trên foo (chi phí = 0,43..3799,80 hàng = 105907 chiều rộng = 4) (thời gian thực tế = 0,037..33.084 hàng = 100000 vòng = 1) |
| Chỉ số Cond: (a = 'a' :: text) |
| Thời gian lập kế hoạch: 0.135 ms |
| Thời gian thực hiện: 54.280 ms |
BRIN trang_per_range = 4:
drop index foo_btree;
explain analyze select sum(b) from foo where a='a';
| KẾ HOẠCH NHANH |
| : ------------------------------------------------- -------------------------------------------------- ----------------------------- |
| Tổng hợp (chi phí = 21595,38..21595,39 hàng = 1 chiều rộng = 8) (thời gian thực tế = 52.455..52.455 hàng = 1 vòng = 1) |
| -> Bitmap Heap Scan trên foo (chi phí = 888,78..21330.61 hàng = 105907 chiều rộng = 4) (thời gian thực tế = 2.738..31.967 hàng = 100000 vòng = 1) |
| Kiểm tra lại Cond: (a = 'a' :: văn bản) |
| Các hàng bị xóa bởi Index Recheck: 96 |
| Khối heap: lossy = 736 |
| -> Quét chỉ mục Bitmap trên foo_brin_4 (chi phí = 0,00..862.30 hàng = 105907 chiều rộng = 0) (thời gian thực tế = 2.720..2.720 hàng = 7360 vòng = 1) |
| Chỉ số Cond: (a = 'a' :: text) |
| Thời gian lập kế hoạch: 0.101 ms |
| Thời gian thực hiện: 52.501 ms |
BRIN trang_per_range = 2:
drop index foo_brin_4;
explain analyze select sum(b) from foo where a='a';
| KẾ HOẠCH NHANH |
| : ------------------------------------------------- -------------------------------------------------- ----------------------------- |
| Tổng hợp (chi phí = 21659,38..21659,39 hàng = 1 chiều rộng = 8) (thời gian thực tế = 53.971..53.971 hàng = 1 vòng = 1) |
| -> Bitmap Heap Scan trên foo (chi phí = 952,78..21394.61 hàng = 105907 chiều rộng = 4) (thời gian thực tế = 5.286..33.492 hàng = 100000 vòng = 1) |
| Kiểm tra lại Cond: (a = 'a' :: văn bản) |
| Các hàng bị xóa bởi Index Recheck: 96 |
| Khối heap: lossy = 736 |
| -> Quét chỉ mục Bitmap trên foo_brin_2 (chi phí = 0,00..926.30 hàng = 105907 chiều rộng = 0) (thời gian thực tế = 5.275..5.275 hàng = 7360 vòng = 1) |
| Chỉ số Cond: (a = 'a' :: text) |
| Thời gian lập kế hoạch: 0,095 ms |
| Thời gian thực hiện: 54.016 ms |
GIN:
drop index foo_brin_2;
explain analyze select sum(b) from foo where a='a';
| KẾ HOẠCH NHANH |
| : ------------------------------------------------- -------------------------------------------------- ------------------------------ |
| Tổng hợp (chi phí = 21687,38..21687,39 hàng = 1 chiều rộng = 8) (thời gian thực tế = 55.331..55.331 hàng = 1 vòng = 1) |
| -> Quét bitmap trên foo (chi phí = 980,78,21422,61 hàng = 105907 chiều rộng = 4) (thời gian thực tế = 12.377..33.956 hàng = 100000 vòng = 1) |
| Kiểm tra lại Cond: (a = 'a' :: văn bản) |
| Khối heap: chính xác = 736 |
| -> Quét chỉ mục Bitmap trên foo_gin (chi phí = 0,00..954.30 hàng = 105907 chiều rộng = 0) (thời gian thực tế = 12.271..12.271 hàng = 100000 vòng = 1) |
| Chỉ số Cond: (a = 'a' :: text) |
| Thời gian lập kế hoạch: 0.118 ms |
| Thời gian thực hiện: 55.366 ms |
dbfiddle ở đây