Commit 77e29068 authored by Tom Lane's avatar Tom Lane

Create an SP-GiST opclass for inet/cidr.

This seems to offer significantly better search performance than the
existing GiST opclass for inet/cidr, at least on data with a wide mix
of network mask lengths.  (That may suggest that the data splitting
heuristics in the GiST opclass could be improved.)

Emre Hasegeli, with mostly-cosmetic adjustments by me

Discussion: <CAE2gYzxtth9qatW_OAqdOjykS0bxq7AYHLuyAQLPgT7H9ZU0Cw@mail.gmail.com>
parent 0fda682e
...@@ -145,6 +145,23 @@ ...@@ -145,6 +145,23 @@
<literal>~&gt;~</> <literal>~&gt;~</>
</entry> </entry>
</row> </row>
<row>
<entry><literal>inet_ops</></entry>
<entry><type>inet</>, <type>cidr</></entry>
<entry>
<literal>&amp;&amp;</>
<literal>&gt;&gt;</>
<literal>&gt;&gt;=</>
<literal>&gt;</>
<literal>&gt;=</>
<literal>&lt;&gt;</>
<literal>&lt;&lt;</>
<literal>&lt;&lt;=</>
<literal>&lt;</>
<literal>&lt;=</>
<literal>=</>
</entry>
</row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
......
...@@ -17,7 +17,7 @@ OBJS = acl.o amutils.o arrayfuncs.o array_expanded.o array_selfuncs.o \ ...@@ -17,7 +17,7 @@ OBJS = acl.o amutils.o arrayfuncs.o array_expanded.o array_selfuncs.o \
geo_ops.o geo_selfuncs.o geo_spgist.o inet_cidr_ntop.o inet_net_pton.o \ geo_ops.o geo_selfuncs.o geo_spgist.o inet_cidr_ntop.o inet_net_pton.o \
int.o int8.o json.o jsonb.o jsonb_gin.o jsonb_op.o jsonb_util.o \ int.o int8.o json.o jsonb.o jsonb_gin.o jsonb_op.o jsonb_util.o \
jsonfuncs.o like.o lockfuncs.o mac.o misc.o nabstime.o name.o \ jsonfuncs.o like.o lockfuncs.o mac.o misc.o nabstime.o name.o \
network.o network_gist.o network_selfuncs.o \ network.o network_gist.o network_selfuncs.o network_spgist.o \
numeric.o numutils.o oid.o oracle_compat.o \ numeric.o numutils.o oid.o oracle_compat.o \
orderedsetaggs.o pg_locale.o pg_lsn.o pg_upgrade_support.o \ orderedsetaggs.o pg_locale.o pg_lsn.o pg_upgrade_support.o \
pgstatfuncs.o \ pgstatfuncs.o \
......
This diff is collapsed.
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201608191 #define CATALOG_VERSION_NO 201608231
#endif #endif
...@@ -863,6 +863,21 @@ DATA(insert ( 3550 869 869 25 s 932 783 0 )); ...@@ -863,6 +863,21 @@ DATA(insert ( 3550 869 869 25 s 932 783 0 ));
DATA(insert ( 3550 869 869 26 s 933 783 0 )); DATA(insert ( 3550 869 869 26 s 933 783 0 ));
DATA(insert ( 3550 869 869 27 s 934 783 0 )); DATA(insert ( 3550 869 869 27 s 934 783 0 ));
/*
* SP-GiST inet_ops
*/
DATA(insert ( 3794 869 869 3 s 3552 4000 0 ));
DATA(insert ( 3794 869 869 18 s 1201 4000 0 ));
DATA(insert ( 3794 869 869 19 s 1202 4000 0 ));
DATA(insert ( 3794 869 869 20 s 1203 4000 0 ));
DATA(insert ( 3794 869 869 21 s 1204 4000 0 ));
DATA(insert ( 3794 869 869 22 s 1205 4000 0 ));
DATA(insert ( 3794 869 869 23 s 1206 4000 0 ));
DATA(insert ( 3794 869 869 24 s 931 4000 0 ));
DATA(insert ( 3794 869 869 25 s 932 4000 0 ));
DATA(insert ( 3794 869 869 26 s 933 4000 0 ));
DATA(insert ( 3794 869 869 27 s 934 4000 0 ));
/* BRIN opclasses */ /* BRIN opclasses */
/* minmax bytea */ /* minmax bytea */
DATA(insert ( 4064 17 17 1 s 1957 3580 0 )); DATA(insert ( 4064 17 17 1 s 1957 3580 0 ));
......
...@@ -428,6 +428,11 @@ DATA(insert ( 3474 3831 3831 2 3470 )); ...@@ -428,6 +428,11 @@ DATA(insert ( 3474 3831 3831 2 3470 ));
DATA(insert ( 3474 3831 3831 3 3471 )); DATA(insert ( 3474 3831 3831 3 3471 ));
DATA(insert ( 3474 3831 3831 4 3472 )); DATA(insert ( 3474 3831 3831 4 3472 ));
DATA(insert ( 3474 3831 3831 5 3473 )); DATA(insert ( 3474 3831 3831 5 3473 ));
DATA(insert ( 3794 869 869 1 3795 ));
DATA(insert ( 3794 869 869 2 3796 ));
DATA(insert ( 3794 869 869 3 3797 ));
DATA(insert ( 3794 869 869 4 3798 ));
DATA(insert ( 3794 869 869 5 3799 ));
DATA(insert ( 4015 600 600 1 4018 )); DATA(insert ( 4015 600 600 1 4018 ));
DATA(insert ( 4015 600 600 2 4019 )); DATA(insert ( 4015 600 600 2 4019 ));
DATA(insert ( 4015 600 600 3 4020 )); DATA(insert ( 4015 600 600 3 4020 ));
......
...@@ -113,6 +113,7 @@ DATA(insert ( 405 float8_ops PGNSP PGUID 1971 701 t 0 )); ...@@ -113,6 +113,7 @@ DATA(insert ( 405 float8_ops PGNSP PGUID 1971 701 t 0 ));
DATA(insert ( 403 inet_ops PGNSP PGUID 1974 869 t 0 )); DATA(insert ( 403 inet_ops PGNSP PGUID 1974 869 t 0 ));
DATA(insert ( 405 inet_ops PGNSP PGUID 1975 869 t 0 )); DATA(insert ( 405 inet_ops PGNSP PGUID 1975 869 t 0 ));
DATA(insert ( 783 inet_ops PGNSP PGUID 3550 869 f 0 )); DATA(insert ( 783 inet_ops PGNSP PGUID 3550 869 f 0 ));
DATA(insert ( 4000 inet_ops PGNSP PGUID 3794 869 t 0 ));
DATA(insert OID = 1979 ( 403 int2_ops PGNSP PGUID 1976 21 t 0 )); DATA(insert OID = 1979 ( 403 int2_ops PGNSP PGUID 1976 21 t 0 ));
#define INT2_BTREE_OPS_OID 1979 #define INT2_BTREE_OPS_OID 1979
DATA(insert ( 405 int2_ops PGNSP PGUID 1977 21 t 0 )); DATA(insert ( 405 int2_ops PGNSP PGUID 1977 21 t 0 ));
......
...@@ -79,6 +79,7 @@ DATA(insert OID = 1974 ( 403 network_ops PGNSP PGUID )); ...@@ -79,6 +79,7 @@ DATA(insert OID = 1974 ( 403 network_ops PGNSP PGUID ));
#define NETWORK_BTREE_FAM_OID 1974 #define NETWORK_BTREE_FAM_OID 1974
DATA(insert OID = 1975 ( 405 network_ops PGNSP PGUID )); DATA(insert OID = 1975 ( 405 network_ops PGNSP PGUID ));
DATA(insert OID = 3550 ( 783 network_ops PGNSP PGUID )); DATA(insert OID = 3550 ( 783 network_ops PGNSP PGUID ));
DATA(insert OID = 3794 ( 4000 network_ops PGNSP PGUID ));
DATA(insert OID = 1976 ( 403 integer_ops PGNSP PGUID )); DATA(insert OID = 1976 ( 403 integer_ops PGNSP PGUID ));
#define INTEGER_BTREE_FAM_OID 1976 #define INTEGER_BTREE_FAM_OID 1976
DATA(insert OID = 1977 ( 405 integer_ops PGNSP PGUID )); DATA(insert OID = 1977 ( 405 integer_ops PGNSP PGUID ));
......
...@@ -2212,6 +2212,18 @@ DESCR("GiST support"); ...@@ -2212,6 +2212,18 @@ DESCR("GiST support");
DATA(insert OID = 3559 ( inet_gist_same PGNSP PGUID 12 1 0 0 0 f f f f t f i s 3 0 2281 "869 869 2281" _null_ _null_ _null_ _null_ _null_ inet_gist_same _null_ _null_ _null_ )); DATA(insert OID = 3559 ( inet_gist_same PGNSP PGUID 12 1 0 0 0 f f f f t f i s 3 0 2281 "869 869 2281" _null_ _null_ _null_ _null_ _null_ inet_gist_same _null_ _null_ _null_ ));
DESCR("GiST support"); DESCR("GiST support");
/* SP-GiST support for inet and cidr */
DATA(insert OID = 3795 ( inet_spg_config PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_spg_config _null_ _null_ _null_ ));
DESCR("SP-GiST support");
DATA(insert OID = 3796 ( inet_spg_choose PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_spg_choose _null_ _null_ _null_ ));
DESCR("SP-GiST support");
DATA(insert OID = 3797 ( inet_spg_picksplit PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_spg_picksplit _null_ _null_ _null_ ));
DESCR("SP-GiST support");
DATA(insert OID = 3798 ( inet_spg_inner_consistent PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_spg_inner_consistent _null_ _null_ _null_ ));
DESCR("SP-GiST support");
DATA(insert OID = 3799 ( inet_spg_leaf_consistent PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 16 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_spg_leaf_consistent _null_ _null_ _null_ ));
DESCR("SP-GiST support");
/* Selectivity estimation for inet and cidr */ /* Selectivity estimation for inet and cidr */
DATA(insert OID = 3560 ( networksel PGNSP PGUID 12 1 0 0 0 f f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ networksel _null_ _null_ _null_ )); DATA(insert OID = 3560 ( networksel PGNSP PGUID 12 1 0 0 0 f f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ networksel _null_ _null_ _null_ ));
DESCR("restriction selectivity for network operators"); DESCR("restriction selectivity for network operators");
......
...@@ -135,6 +135,15 @@ extern Datum inet_gist_penalty(PG_FUNCTION_ARGS); ...@@ -135,6 +135,15 @@ extern Datum inet_gist_penalty(PG_FUNCTION_ARGS);
extern Datum inet_gist_picksplit(PG_FUNCTION_ARGS); extern Datum inet_gist_picksplit(PG_FUNCTION_ARGS);
extern Datum inet_gist_same(PG_FUNCTION_ARGS); extern Datum inet_gist_same(PG_FUNCTION_ARGS);
/*
* SP-GiST support functions in network_spgist.c
*/
extern Datum inet_spg_config(PG_FUNCTION_ARGS);
extern Datum inet_spg_choose(PG_FUNCTION_ARGS);
extern Datum inet_spg_picksplit(PG_FUNCTION_ARGS);
extern Datum inet_spg_inner_consistent(PG_FUNCTION_ARGS);
extern Datum inet_spg_leaf_consistent(PG_FUNCTION_ARGS);
/* /*
* Estimation functions in network_selfuncs.c * Estimation functions in network_selfuncs.c
*/ */
......
...@@ -411,6 +411,154 @@ SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i; ...@@ -411,6 +411,154 @@ SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i;
SET enable_seqscan TO on; SET enable_seqscan TO on;
DROP INDEX inet_idx2; DROP INDEX inet_idx2;
-- check that spgist index works correctly
CREATE INDEX inet_idx3 ON inet_tbl using spgist (i);
SET enable_seqscan TO off;
SELECT * FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i;
c | i
----------------+------------------
192.168.1.0/24 | 192.168.1.0/25
192.168.1.0/24 | 192.168.1.255/25
192.168.1.0/26 | 192.168.1.226
(3 rows)
SELECT * FROM inet_tbl WHERE i <<= '192.168.1.0/24'::cidr ORDER BY i;
c | i
----------------+------------------
192.168.1.0/24 | 192.168.1.0/24
192.168.1.0/24 | 192.168.1.226/24
192.168.1.0/24 | 192.168.1.255/24
192.168.1.0/24 | 192.168.1.0/25
192.168.1.0/24 | 192.168.1.255/25
192.168.1.0/26 | 192.168.1.226
(6 rows)
SELECT * FROM inet_tbl WHERE i && '192.168.1.0/24'::cidr ORDER BY i;
c | i
----------------+------------------
192.168.1.0/24 | 192.168.1.0/24
192.168.1.0/24 | 192.168.1.226/24
192.168.1.0/24 | 192.168.1.255/24
192.168.1.0/24 | 192.168.1.0/25
192.168.1.0/24 | 192.168.1.255/25
192.168.1.0/26 | 192.168.1.226
(6 rows)
SELECT * FROM inet_tbl WHERE i >>= '192.168.1.0/24'::cidr ORDER BY i;
c | i
----------------+------------------
192.168.1.0/24 | 192.168.1.0/24
192.168.1.0/24 | 192.168.1.226/24
192.168.1.0/24 | 192.168.1.255/24
(3 rows)
SELECT * FROM inet_tbl WHERE i >> '192.168.1.0/24'::cidr ORDER BY i;
c | i
---+---
(0 rows)
SELECT * FROM inet_tbl WHERE i < '192.168.1.0/24'::cidr ORDER BY i;
c | i
-------------+-------------
10.0.0.0/8 | 9.1.2.3/8
10.0.0.0/32 | 10.1.2.3/8
10.0.0.0/8 | 10.1.2.3/8
10.0.0.0/8 | 10.1.2.3/8
10.1.0.0/16 | 10.1.2.3/16
10.1.2.0/24 | 10.1.2.3/24
10.1.2.3/32 | 10.1.2.3
10.0.0.0/8 | 11.1.2.3/8
(8 rows)
SELECT * FROM inet_tbl WHERE i <= '192.168.1.0/24'::cidr ORDER BY i;
c | i
----------------+----------------
10.0.0.0/8 | 9.1.2.3/8
10.0.0.0/8 | 10.1.2.3/8
10.0.0.0/32 | 10.1.2.3/8
10.0.0.0/8 | 10.1.2.3/8
10.1.0.0/16 | 10.1.2.3/16
10.1.2.0/24 | 10.1.2.3/24
10.1.2.3/32 | 10.1.2.3
10.0.0.0/8 | 11.1.2.3/8
192.168.1.0/24 | 192.168.1.0/24
(9 rows)
SELECT * FROM inet_tbl WHERE i = '192.168.1.0/24'::cidr ORDER BY i;
c | i
----------------+----------------
192.168.1.0/24 | 192.168.1.0/24
(1 row)
SELECT * FROM inet_tbl WHERE i >= '192.168.1.0/24'::cidr ORDER BY i;
c | i
--------------------+------------------
192.168.1.0/24 | 192.168.1.0/24
192.168.1.0/24 | 192.168.1.226/24
192.168.1.0/24 | 192.168.1.255/24
192.168.1.0/24 | 192.168.1.0/25
192.168.1.0/24 | 192.168.1.255/25
192.168.1.0/26 | 192.168.1.226
::ffff:1.2.3.4/128 | ::4.3.2.1/24
10:23::f1/128 | 10:23::f1/64
10:23::8000/113 | 10:23::ffff
(9 rows)
SELECT * FROM inet_tbl WHERE i > '192.168.1.0/24'::cidr ORDER BY i;
c | i
--------------------+------------------
192.168.1.0/24 | 192.168.1.226/24
192.168.1.0/24 | 192.168.1.255/24
192.168.1.0/24 | 192.168.1.0/25
192.168.1.0/24 | 192.168.1.255/25
192.168.1.0/26 | 192.168.1.226
::ffff:1.2.3.4/128 | ::4.3.2.1/24
10:23::f1/128 | 10:23::f1/64
10:23::8000/113 | 10:23::ffff
(8 rows)
SELECT * FROM inet_tbl WHERE i <> '192.168.1.0/24'::cidr ORDER BY i;
c | i
--------------------+------------------
10.0.0.0/8 | 9.1.2.3/8
10.0.0.0/8 | 10.1.2.3/8
10.0.0.0/32 | 10.1.2.3/8
10.0.0.0/8 | 10.1.2.3/8
10.1.0.0/16 | 10.1.2.3/16
10.1.2.0/24 | 10.1.2.3/24
10.1.2.3/32 | 10.1.2.3
10.0.0.0/8 | 11.1.2.3/8
192.168.1.0/24 | 192.168.1.226/24
192.168.1.0/24 | 192.168.1.255/24
192.168.1.0/24 | 192.168.1.0/25
192.168.1.0/24 | 192.168.1.255/25
192.168.1.0/26 | 192.168.1.226
::ffff:1.2.3.4/128 | ::4.3.2.1/24
10:23::f1/128 | 10:23::f1/64
10:23::8000/113 | 10:23::ffff
(16 rows)
-- test index-only scans
EXPLAIN (COSTS OFF)
SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i;
QUERY PLAN
---------------------------------------------------
Sort
Sort Key: i
-> Index Only Scan using inet_idx3 on inet_tbl
Index Cond: (i << '192.168.1.0/24'::inet)
(4 rows)
SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i;
i
------------------
192.168.1.0/25
192.168.1.255/25
192.168.1.226
(3 rows)
SET enable_seqscan TO on;
DROP INDEX inet_idx3;
-- simple tests of inet boolean and arithmetic operators -- simple tests of inet boolean and arithmetic operators
SELECT i, ~i AS "~i" FROM inet_tbl; SELECT i, ~i AS "~i" FROM inet_tbl;
i | ~i i | ~i
......
...@@ -1819,7 +1819,16 @@ ORDER BY 1, 2, 3; ...@@ -1819,7 +1819,16 @@ ORDER BY 1, 2, 3;
4000 | 15 | > 4000 | 15 | >
4000 | 16 | @> 4000 | 16 | @>
4000 | 18 | = 4000 | 18 | =
(112 rows) 4000 | 19 | <>
4000 | 20 | <
4000 | 21 | <=
4000 | 22 | >
4000 | 23 | >=
4000 | 24 | <<
4000 | 25 | <<=
4000 | 26 | >>
4000 | 27 | >>=
(121 rows)
-- Check that all opclass search operators have selectivity estimators. -- Check that all opclass search operators have selectivity estimators.
-- This is not absolutely required, but it seems a reasonable thing -- This is not absolutely required, but it seems a reasonable thing
......
...@@ -93,6 +93,29 @@ SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i; ...@@ -93,6 +93,29 @@ SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i;
SET enable_seqscan TO on; SET enable_seqscan TO on;
DROP INDEX inet_idx2; DROP INDEX inet_idx2;
-- check that spgist index works correctly
CREATE INDEX inet_idx3 ON inet_tbl using spgist (i);
SET enable_seqscan TO off;
SELECT * FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i;
SELECT * FROM inet_tbl WHERE i <<= '192.168.1.0/24'::cidr ORDER BY i;
SELECT * FROM inet_tbl WHERE i && '192.168.1.0/24'::cidr ORDER BY i;
SELECT * FROM inet_tbl WHERE i >>= '192.168.1.0/24'::cidr ORDER BY i;
SELECT * FROM inet_tbl WHERE i >> '192.168.1.0/24'::cidr ORDER BY i;
SELECT * FROM inet_tbl WHERE i < '192.168.1.0/24'::cidr ORDER BY i;
SELECT * FROM inet_tbl WHERE i <= '192.168.1.0/24'::cidr ORDER BY i;
SELECT * FROM inet_tbl WHERE i = '192.168.1.0/24'::cidr ORDER BY i;
SELECT * FROM inet_tbl WHERE i >= '192.168.1.0/24'::cidr ORDER BY i;
SELECT * FROM inet_tbl WHERE i > '192.168.1.0/24'::cidr ORDER BY i;
SELECT * FROM inet_tbl WHERE i <> '192.168.1.0/24'::cidr ORDER BY i;
-- test index-only scans
EXPLAIN (COSTS OFF)
SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i;
SELECT i FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i;
SET enable_seqscan TO on;
DROP INDEX inet_idx3;
-- simple tests of inet boolean and arithmetic operators -- simple tests of inet boolean and arithmetic operators
SELECT i, ~i AS "~i" FROM inet_tbl; SELECT i, ~i AS "~i" FROM inet_tbl;
SELECT i, c, i & c AS "and" FROM inet_tbl; SELECT i, c, i & c AS "and" FROM inet_tbl;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment