mirror of
https://github.com/postgres/postgres.git
synced 2026-05-25 02:40:42 -04:00
PostgreSQL provides set of template index access methods, where opclasses have much freedom in the semantics of indexing. These index AMs are GiST, GIN, SP-GiST and BRIN. There opclasses define representation of keys, operations on them and supported search strategies. So, it's natural that opclasses may be faced some tradeoffs, which require user-side decision. This commit implements opclass parameters allowing users to set some values, which tell opclass how to index the particular dataset. This commit doesn't introduce new storage in system catalog. Instead it uses pg_attribute.attoptions, which is used for table column storage options but unused for index attributes. In order to evade changing signature of each opclass support function, we implement unified way to pass options to opclass support functions. Options are set to fn_expr as the constant bytea expression. It's possible due to the fact that opclass support functions are executed outside of expressions, so fn_expr is unused for them. This commit comes with some examples of opclass options usage. We parametrize signature length in GiST. That applies to multiple opclasses: tsvector_ops, gist__intbig_ops, gist_ltree_ops, gist__ltree_ops, gist_trgm_ops and gist_hstore_ops. Also we parametrize maximum number of integer ranges for gist__int_ops. However, the main future usage of this feature is expected to be json, where users would be able to specify which way to index particular json parts. Catversion is bumped. Discussion: https://postgr.es/m/d22c3a18-31c7-1879-fc11-4c1ce2f5e5af%40postgrespro.ru Author: Nikita Glukhov, revised by me Reviwed-by: Nikolay Shaplov, Robert Haas, Tom Lane, Tomas Vondra, Alvaro Herrera
185 lines
6.2 KiB
SQL
185 lines
6.2 KiB
SQL
--
|
|
-- BTREE_INDEX
|
|
-- test retrieval of min/max keys for each index
|
|
--
|
|
|
|
SELECT b.*
|
|
FROM bt_i4_heap b
|
|
WHERE b.seqno < 1;
|
|
|
|
SELECT b.*
|
|
FROM bt_i4_heap b
|
|
WHERE b.seqno >= 9999;
|
|
|
|
SELECT b.*
|
|
FROM bt_i4_heap b
|
|
WHERE b.seqno = 4500;
|
|
|
|
SELECT b.*
|
|
FROM bt_name_heap b
|
|
WHERE b.seqno < '1'::name;
|
|
|
|
SELECT b.*
|
|
FROM bt_name_heap b
|
|
WHERE b.seqno >= '9999'::name;
|
|
|
|
SELECT b.*
|
|
FROM bt_name_heap b
|
|
WHERE b.seqno = '4500'::name;
|
|
|
|
SELECT b.*
|
|
FROM bt_txt_heap b
|
|
WHERE b.seqno < '1'::text;
|
|
|
|
SELECT b.*
|
|
FROM bt_txt_heap b
|
|
WHERE b.seqno >= '9999'::text;
|
|
|
|
SELECT b.*
|
|
FROM bt_txt_heap b
|
|
WHERE b.seqno = '4500'::text;
|
|
|
|
SELECT b.*
|
|
FROM bt_f8_heap b
|
|
WHERE b.seqno < '1'::float8;
|
|
|
|
SELECT b.*
|
|
FROM bt_f8_heap b
|
|
WHERE b.seqno >= '9999'::float8;
|
|
|
|
SELECT b.*
|
|
FROM bt_f8_heap b
|
|
WHERE b.seqno = '4500'::float8;
|
|
|
|
--
|
|
-- Check correct optimization of LIKE (special index operator support)
|
|
-- for both indexscan and bitmapscan cases
|
|
--
|
|
|
|
set enable_seqscan to false;
|
|
set enable_indexscan to true;
|
|
set enable_bitmapscan to false;
|
|
explain (costs off)
|
|
select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
|
|
select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
|
|
explain (costs off)
|
|
select proname from pg_proc where proname ilike '00%foo' order by 1;
|
|
select proname from pg_proc where proname ilike '00%foo' order by 1;
|
|
explain (costs off)
|
|
select proname from pg_proc where proname ilike 'ri%foo' order by 1;
|
|
|
|
set enable_indexscan to false;
|
|
set enable_bitmapscan to true;
|
|
explain (costs off)
|
|
select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
|
|
select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
|
|
explain (costs off)
|
|
select proname from pg_proc where proname ilike '00%foo' order by 1;
|
|
select proname from pg_proc where proname ilike '00%foo' order by 1;
|
|
explain (costs off)
|
|
select proname from pg_proc where proname ilike 'ri%foo' order by 1;
|
|
|
|
reset enable_seqscan;
|
|
reset enable_indexscan;
|
|
reset enable_bitmapscan;
|
|
|
|
-- Also check LIKE optimization with binary-compatible cases
|
|
|
|
create temp table btree_bpchar (f1 text collate "C");
|
|
create index on btree_bpchar(f1 bpchar_ops) WITH (deduplicate_items=on);
|
|
insert into btree_bpchar values ('foo'), ('fool'), ('bar'), ('quux');
|
|
-- doesn't match index:
|
|
explain (costs off)
|
|
select * from btree_bpchar where f1 like 'foo';
|
|
select * from btree_bpchar where f1 like 'foo';
|
|
explain (costs off)
|
|
select * from btree_bpchar where f1 like 'foo%';
|
|
select * from btree_bpchar where f1 like 'foo%';
|
|
-- these do match the index:
|
|
explain (costs off)
|
|
select * from btree_bpchar where f1::bpchar like 'foo';
|
|
select * from btree_bpchar where f1::bpchar like 'foo';
|
|
explain (costs off)
|
|
select * from btree_bpchar where f1::bpchar like 'foo%';
|
|
select * from btree_bpchar where f1::bpchar like 'foo%';
|
|
|
|
-- get test coverage for "single value" deduplication strategy:
|
|
insert into btree_bpchar select 'foo' from generate_series(1,1500);
|
|
|
|
--
|
|
-- Perform unique checking, with and without the use of deduplication
|
|
--
|
|
CREATE TABLE dedup_unique_test_table (a int) WITH (autovacuum_enabled=false);
|
|
CREATE UNIQUE INDEX dedup_unique ON dedup_unique_test_table (a) WITH (deduplicate_items=on);
|
|
CREATE UNIQUE INDEX plain_unique ON dedup_unique_test_table (a) WITH (deduplicate_items=off);
|
|
-- Generate enough garbage tuples in index to ensure that even the unique index
|
|
-- with deduplication enabled has to check multiple leaf pages during unique
|
|
-- checking (at least with a BLCKSZ of 8192 or less)
|
|
DO $$
|
|
BEGIN
|
|
FOR r IN 1..1350 LOOP
|
|
DELETE FROM dedup_unique_test_table;
|
|
INSERT INTO dedup_unique_test_table SELECT 1;
|
|
END LOOP;
|
|
END$$;
|
|
|
|
--
|
|
-- Test B-tree fast path (cache rightmost leaf page) optimization.
|
|
--
|
|
|
|
-- First create a tree that's at least three levels deep (i.e. has one level
|
|
-- between the root and leaf levels). The text inserted is long. It won't be
|
|
-- compressed because we use plain storage in the table. Only a few index
|
|
-- tuples fit on each internal page, allowing us to get a tall tree with few
|
|
-- pages. (A tall tree is required to trigger caching.)
|
|
--
|
|
-- The text column must be the leading column in the index, since suffix
|
|
-- truncation would otherwise truncate tuples on internal pages, leaving us
|
|
-- with a short tree.
|
|
create table btree_tall_tbl(id int4, t text);
|
|
alter table btree_tall_tbl alter COLUMN t set storage plain;
|
|
create index btree_tall_idx on btree_tall_tbl (t, id) with (fillfactor = 10);
|
|
insert into btree_tall_tbl select g, repeat('x', 250)
|
|
from generate_series(1, 130) g;
|
|
|
|
--
|
|
-- Test vacuum_cleanup_index_scale_factor
|
|
--
|
|
|
|
-- Simple create
|
|
create table btree_test(a int);
|
|
create index btree_idx1 on btree_test(a) with (vacuum_cleanup_index_scale_factor = 40.0);
|
|
select reloptions from pg_class WHERE oid = 'btree_idx1'::regclass;
|
|
|
|
-- Fail while setting improper values
|
|
create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = -10.0);
|
|
create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = 100.0);
|
|
create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = 'string');
|
|
create index btree_idx_err on btree_test(a) with (vacuum_cleanup_index_scale_factor = true);
|
|
|
|
-- Simple ALTER INDEX
|
|
alter index btree_idx1 set (vacuum_cleanup_index_scale_factor = 70.0);
|
|
select reloptions from pg_class WHERE oid = 'btree_idx1'::regclass;
|
|
|
|
--
|
|
-- Test for multilevel page deletion
|
|
--
|
|
CREATE TABLE delete_test_table (a bigint, b bigint, c bigint, d bigint);
|
|
INSERT INTO delete_test_table SELECT i, 1, 2, 3 FROM generate_series(1,80000) i;
|
|
ALTER TABLE delete_test_table ADD PRIMARY KEY (a,b,c,d);
|
|
-- Delete most entries, and vacuum, deleting internal pages and creating "fast
|
|
-- root"
|
|
DELETE FROM delete_test_table WHERE a < 79990;
|
|
VACUUM delete_test_table;
|
|
|
|
--
|
|
-- Test B-tree insertion with a metapage update (XLOG_BTREE_INSERT_META
|
|
-- WAL record type). This happens when a "fast root" page is split. This
|
|
-- also creates coverage for nbtree FSM page recycling.
|
|
--
|
|
-- The vacuum above should've turned the leaf page into a fast root. We just
|
|
-- need to insert some rows to cause the fast root page to split.
|
|
INSERT INTO delete_test_table SELECT i, 1, 2, 3 FROM generate_series(1,1000) i;
|
|
|
|
-- Test unsupported btree opclass parameters
|
|
create index on btree_tall_tbl (id int4_ops(foo=1));
|