1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-07 00:36:50 +03:00

Add BRIN infrastructure for "inclusion" opclasses

This lets BRIN be used with R-Tree-like indexing strategies.

Also provided are operator classes for range types, box and inet/cidr.
The infrastructure provided here should be sufficient to create operator
classes for similar datatypes; for instance, opclasses for PostGIS
geometries should be doable, though we didn't try to implement one.

(A box/point opclass was also submitted, but we ripped it out before
commit because the handling of floating point comparisons in existing
code is inconsistent and would generate corrupt indexes.)

Author: Emre Hasegeli.  Cosmetic changes by me
Review: Andreas Karlsson
This commit is contained in:
Alvaro Herrera
2015-05-15 18:05:22 -03:00
parent 199f5973c5
commit b0b7be6133
18 changed files with 928 additions and 105 deletions

View File

@ -23,7 +23,9 @@ CREATE TABLE brintest (byteacol bytea,
varbitcol bit varying(16),
numericcol numeric,
uuidcol uuid,
lsncol pg_lsn
int4rangecol int4range,
lsncol pg_lsn,
boxcol box
) WITH (fillfactor=10, autovacuum_enabled=off);
INSERT INTO brintest SELECT
repeat(stringu1, 8)::bytea,
@ -50,12 +52,15 @@ INSERT INTO brintest SELECT
tenthous::bit(16)::varbit,
tenthous::numeric(36,30) * fivethous * even / (hundred + 1),
format('%s%s-%s-%s-%s-%s%s%s', to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'))::uuid,
format('%s/%s%s', odd, even, tenthous)::pg_lsn
FROM tenk1 LIMIT 25;
int4range(thousand, twothousand),
format('%s/%s%s', odd, even, tenthous)::pg_lsn,
box(point(odd, even), point(thousand, twothousand))
FROM tenk1 LIMIT 100;
-- throw in some NULL's and different values
INSERT INTO brintest (inetcol, cidrcol) SELECT
INSERT INTO brintest (inetcol, cidrcol, int4rangecol) SELECT
inet 'fe80::6e40:8ff:fea9:8c46' + tenthous,
cidr 'fe80::6e40:8ff:fea9:8c46' + tenthous
cidr 'fe80::6e40:8ff:fea9:8c46' + tenthous,
'empty'::int4range
FROM tenk1 LIMIT 25;
CREATE INDEX brinidx ON brintest USING brin (
byteacol,
@ -70,6 +75,7 @@ CREATE INDEX brinidx ON brintest USING brin (
float4col,
float8col,
macaddrcol,
inetcol inet_inclusion_ops,
inetcol inet_minmax_ops,
bpcharcol,
datecol,
@ -82,7 +88,9 @@ CREATE INDEX brinidx ON brintest USING brin (
varbitcol,
numericcol,
uuidcol,
lsncol
int4rangecol,
lsncol,
boxcol
) with (pages_per_range = 1);
CREATE TABLE brinopers (colname name, typ text, op text[], value text[],
check (cardinality(op) = cardinality(value)));
@ -128,7 +136,12 @@ INSERT INTO brinopers VALUES
('varbitcol', 'varbit(16)', '{>, >=, =, <=, <}', '{0000000000000100, 0000000000000100, 0001010001100110, 1111111111111000, 1111111111111000}'),
('numericcol', 'numeric', '{>, >=, =, <=, <}', '{0.00, 0.01, 2268164.347826086956521739130434782609, 99470151.9, 99470151.9}'),
('uuidcol', 'uuid', '{>, >=, =, <=, <}', '{00040004-0004-0004-0004-000400040004, 00040004-0004-0004-0004-000400040004, 52225222-5222-5222-5222-522252225222, 99989998-9998-9998-9998-999899989998, 99989998-9998-9998-9998-999899989998}'),
('lsncol', 'pg_lsn', '{>, >=, =, <=, <, IS, IS NOT}', '{0/1200, 0/1200, 44/455222, 198/1999799, 198/1999799, NULL, NULL}');
('int4rangecol', 'int4range', '{<<, &<, &&, &>, >>, @>, <@, =, <, <=, >, >=}', '{"[10000,)","[10000,)","(,]","[3,4)","[36,44)","(1500,1501]","[3,4)","[222,1222)","[36,44)","[43,1043)","[367,4466)","[519,)"}'),
('int4rangecol', 'int4range', '{@>, <@, =, <=, >, >=}', '{empty, empty, empty, empty, empty, empty}'),
('int4rangecol', 'int4', '{@>}', '{1500}'),
('lsncol', 'pg_lsn', '{>, >=, =, <=, <, IS, IS NOT}', '{0/1200, 0/1200, 44/455222, 198/1999799, 198/1999799, NULL, NULL}'),
('boxcol', 'point', '{@>}', '{"(500,43)"}'),
('boxcol', 'box', '{<<, &<, &&, &>, >>, <<|, &<|, |&>, |>>, @>, <@, ~=}', '{"((1000,2000),(3000,4000))","((1,2),(3000,4000))","((1,2),(3000,4000))","((1,2),(3000,4000))","((1,2),(3,4))","((1000,2000),(3000,4000))","((1,2000),(3,4000))","((1000,2),(3000,4))","((1,2),(3,4))","((1,2),(300,400))","((1,2),(3000,4000))","((222,1222),(44,45))"}');
DO $x$
DECLARE
r record;
@ -222,7 +235,9 @@ INSERT INTO brintest SELECT
tenthous::bit(16)::varbit,
tenthous::numeric(36,30) * fivethous * even / (hundred + 1),
format('%s%s-%s-%s-%s-%s%s%s', to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'))::uuid,
format('%s/%s%s', odd, even, tenthous)::pg_lsn
int4range(thousand, twothousand),
format('%s/%s%s', odd, even, tenthous)::pg_lsn,
box(point(odd, even), point(thousand, twothousand))
FROM tenk1 LIMIT 5 OFFSET 5;
SELECT brin_summarize_new_values('brinidx'::regclass);
brin_summarize_new_values

View File

@ -1657,10 +1657,33 @@ ORDER BY 1, 2, 3;
2742 | 10 | ?|
2742 | 11 | ?&
3580 | 1 | <
3580 | 1 | <<
3580 | 2 | &<
3580 | 2 | <=
3580 | 3 | &&
3580 | 3 | =
3580 | 4 | &>
3580 | 4 | >=
3580 | 5 | >
3580 | 5 | >>
3580 | 6 | ~=
3580 | 7 | >>=
3580 | 7 | @>
3580 | 8 | <<=
3580 | 8 | <@
3580 | 9 | &<|
3580 | 10 | <<|
3580 | 11 | |>>
3580 | 12 | |&>
3580 | 16 | @>
3580 | 17 | -|-
3580 | 18 | =
3580 | 20 | <
3580 | 21 | <=
3580 | 22 | >
3580 | 23 | >=
3580 | 24 | >>
3580 | 26 | <<
4000 | 1 | <<
4000 | 1 | ~<~
4000 | 2 | &<
@ -1683,7 +1706,7 @@ ORDER BY 1, 2, 3;
4000 | 15 | >
4000 | 16 | @>
4000 | 18 | =
(85 rows)
(108 rows)
-- Check that all opclass search operators have selectivity estimators.
-- This is not absolutely required, but it seems a reasonable thing

View File

@ -23,7 +23,9 @@ CREATE TABLE brintest (byteacol bytea,
varbitcol bit varying(16),
numericcol numeric,
uuidcol uuid,
lsncol pg_lsn
int4rangecol int4range,
lsncol pg_lsn,
boxcol box
) WITH (fillfactor=10, autovacuum_enabled=off);
INSERT INTO brintest SELECT
@ -51,13 +53,16 @@ INSERT INTO brintest SELECT
tenthous::bit(16)::varbit,
tenthous::numeric(36,30) * fivethous * even / (hundred + 1),
format('%s%s-%s-%s-%s-%s%s%s', to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'))::uuid,
format('%s/%s%s', odd, even, tenthous)::pg_lsn
FROM tenk1 LIMIT 25;
int4range(thousand, twothousand),
format('%s/%s%s', odd, even, tenthous)::pg_lsn,
box(point(odd, even), point(thousand, twothousand))
FROM tenk1 LIMIT 100;
-- throw in some NULL's and different values
INSERT INTO brintest (inetcol, cidrcol) SELECT
INSERT INTO brintest (inetcol, cidrcol, int4rangecol) SELECT
inet 'fe80::6e40:8ff:fea9:8c46' + tenthous,
cidr 'fe80::6e40:8ff:fea9:8c46' + tenthous
cidr 'fe80::6e40:8ff:fea9:8c46' + tenthous,
'empty'::int4range
FROM tenk1 LIMIT 25;
CREATE INDEX brinidx ON brintest USING brin (
@ -73,6 +78,7 @@ CREATE INDEX brinidx ON brintest USING brin (
float4col,
float8col,
macaddrcol,
inetcol inet_inclusion_ops,
inetcol inet_minmax_ops,
bpcharcol,
datecol,
@ -85,7 +91,9 @@ CREATE INDEX brinidx ON brintest USING brin (
varbitcol,
numericcol,
uuidcol,
lsncol
int4rangecol,
lsncol,
boxcol
) with (pages_per_range = 1);
CREATE TABLE brinopers (colname name, typ text, op text[], value text[],
@ -133,7 +141,12 @@ INSERT INTO brinopers VALUES
('varbitcol', 'varbit(16)', '{>, >=, =, <=, <}', '{0000000000000100, 0000000000000100, 0001010001100110, 1111111111111000, 1111111111111000}'),
('numericcol', 'numeric', '{>, >=, =, <=, <}', '{0.00, 0.01, 2268164.347826086956521739130434782609, 99470151.9, 99470151.9}'),
('uuidcol', 'uuid', '{>, >=, =, <=, <}', '{00040004-0004-0004-0004-000400040004, 00040004-0004-0004-0004-000400040004, 52225222-5222-5222-5222-522252225222, 99989998-9998-9998-9998-999899989998, 99989998-9998-9998-9998-999899989998}'),
('lsncol', 'pg_lsn', '{>, >=, =, <=, <, IS, IS NOT}', '{0/1200, 0/1200, 44/455222, 198/1999799, 198/1999799, NULL, NULL}');
('int4rangecol', 'int4range', '{<<, &<, &&, &>, >>, @>, <@, =, <, <=, >, >=}', '{"[10000,)","[10000,)","(,]","[3,4)","[36,44)","(1500,1501]","[3,4)","[222,1222)","[36,44)","[43,1043)","[367,4466)","[519,)"}'),
('int4rangecol', 'int4range', '{@>, <@, =, <=, >, >=}', '{empty, empty, empty, empty, empty, empty}'),
('int4rangecol', 'int4', '{@>}', '{1500}'),
('lsncol', 'pg_lsn', '{>, >=, =, <=, <, IS, IS NOT}', '{0/1200, 0/1200, 44/455222, 198/1999799, 198/1999799, NULL, NULL}'),
('boxcol', 'point', '{@>}', '{"(500,43)"}'),
('boxcol', 'box', '{<<, &<, &&, &>, >>, <<|, &<|, |&>, |>>, @>, <@, ~=}', '{"((1000,2000),(3000,4000))","((1,2),(3000,4000))","((1,2),(3000,4000))","((1,2),(3000,4000))","((1,2),(3,4))","((1000,2000),(3000,4000))","((1,2000),(3,4000))","((1000,2),(3000,4))","((1,2),(3,4))","((1,2),(300,400))","((1,2),(3000,4000))","((222,1222),(44,45))"}');
DO $x$
DECLARE
@ -229,7 +242,9 @@ INSERT INTO brintest SELECT
tenthous::bit(16)::varbit,
tenthous::numeric(36,30) * fivethous * even / (hundred + 1),
format('%s%s-%s-%s-%s-%s%s%s', to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'), to_char(tenthous, 'FM0000'))::uuid,
format('%s/%s%s', odd, even, tenthous)::pg_lsn
int4range(thousand, twothousand),
format('%s/%s%s', odd, even, tenthous)::pg_lsn,
box(point(odd, even), point(thousand, twothousand))
FROM tenk1 LIMIT 5 OFFSET 5;
SELECT brin_summarize_new_values('brinidx'::regclass);