标簽
PostgreSQL , json , 索引 , gin , btree_gin , 範圍檢索 , 表達式索引
https://github.com/digoal/blog/blob/master/201807/20180702_02.md#%E8%83%8C%E6%99%AF 背景
JSON,JSONB是PG從9就開始引入的資料類型,開發人員非常喜歡,對于JSON裡面的内容的檢索,我們可以使用GIN索引,目前直接對JSON字段建立GIN索引,可以支援任意PATH的等值、包含檢索。
https://www.postgresql.org/docs/10/static/datatype-json.html#JSON-INDEXING但是,在多數場景中,我們可能還需要範圍檢索的需求,例如消費範圍,年齡範圍,收入範圍等等。
使用表達式組合索引,很好的滿足需求。
https://github.com/digoal/blog/blob/master/201807/20180702_02.md#%E4%BE%8B%E5%AD%90 例子
https://github.com/digoal/blog/blob/master/201807/20180702_02.md#%E5%8D%95key%E7%9B%B4%E6%8E%A5%E7%94%A8btree%E7%B4%A2%E5%BC%95 單KEY,直接用btree索引
postgres=# create table test (id int, js jsonb);
CREATE TABLE
postgres=# create index idx_test_2 on test using btree (((js->>'key1')::int));
CREATE INDEX
postgres=# explain select * from test where (js->>'key1')::int between 1 and 10 ;
QUERY PLAN
------------------------------------------------------------------------------------------------------
Index Scan using idx_test_2 on test (cost=0.15..24.27 rows=6 width=36)
Index Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10))
(2 rows)
https://github.com/digoal/blog/blob/master/201807/20180702_02.md#%E5%A4%9Akey%E6%B7%B7%E5%90%88%E4%BD%BF%E7%94%A8btree_gin-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%B4%A2%E5%BC%95 多KEY混合,使用btree_gin, 表達式索引
例如需要查詢key1,key2,key3的任意組合範圍查詢。
postgres=# create extension btree_gin;
CREATE EXTENSION
postgres=# create index idx_test_1 on test using gin (((js->>'key1')::int), ((js->>'key2')::int), ((js->>'key3')::int));
CREATE INDEX
postgres=# explain select * from test where (js->>'key1')::int between 1 and 10
postgres-# ;
QUERY PLAN
------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on test (cost=24.07..33.64 rows=6 width=36)
Recheck Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10))
-> Bitmap Index Scan on idx_test_1 (cost=0.00..24.06 rows=6 width=0)
Index Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10))
(4 rows)
postgres=# explain select * from test where (js->>'key1')::int between 1 and 10 or (js->>'key2')::int between 1 and 15;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on test (cost=48.13..59.32 rows=13 width=36)
Recheck Cond: (((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10)) OR ((((js ->> 'key2'::text))::integer >= 1) AND (((js ->> 'key2'::text))::integer <= 15)))
-> BitmapOr (cost=48.13..48.13 rows=13 width=0)
-> Bitmap Index Scan on idx_test_1 (cost=0.00..24.06 rows=6 width=0)
Index Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10))
-> Bitmap Index Scan on idx_test_1 (cost=0.00..24.06 rows=6 width=0)
Index Cond: ((((js ->> 'key2'::text))::integer >= 1) AND (((js ->> 'key2'::text))::integer <= 15))
(7 rows)
postgres=# explain select * from test where (js->>'key1')::int between 1 and 10 and (js->>'key2')::int between 1 and 15;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on test (cost=40.00..44.05 rows=1 width=36)
Recheck Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10) AND (((js ->> 'key2'::text))::integer >= 1) AND (((js ->> 'key2'::text))::integer <= 15))
-> Bitmap Index Scan on idx_test_1 (cost=0.00..40.00 rows=1 width=0)
Index Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10) AND (((js ->> 'key2'::text))::integer >= 1) AND (((js ->> 'key2'::text))::integer <= 15))
(4 rows)