关于json:PostgreSQL索引JSONB数组

PostgreSQL indexing JSONB array

这是我的json

1
2
3
4
5
6
7
jsondata
------------------------------------
{"key1": 1,"keyset": [10, 20, 30]}
{"key1": 1,"keyset": [10, 20]}
{"key1": 1,"keyset": [30]}
{"key1": 1 }
{"key1": 1,"key2": 1}

我尝试为上面的例子创建索引keyset
使用btree的第一个索引

1
CREATE INDEX test_keyset ON test_table (jsondata->'keyset');

第二个指数使用杜松子酒

1
CREATE INDEX test_keyset ON test_table USING GIN(jsondata->'keyset');

和查询选择keyset值10,

1
2
3
4
5
SELECT jsondata
FROM test
   JOIN LATERAL jsonb_array_elements_text(jsondata->'keyset') a(v)
      ON TRUE
WHERE a.v::INTEGER = 10;

但它正在进行顺序扫描(检查所有行),任何人都可以建议我使用哪种索引方法是正确的(btree或gin)以及使用索引从json获取数据的有效方法,例如,我是postgres的新手


在表达式jsondata->'keyset'上使用gin索引:

1
CREATE INDEX test_keyset ON test USING gin((jsondata->'keyset'));

您应该将查询中的表达式与@>运算符结合使用:

1
2
3
4
5
6
7
8
9
SELECT jsondata
FROM test
WHERE jsondata->'keyset' @> '10'

              jsondata              
-------------------------------------
 {"key1": 1,"keyset": [10, 20, 30]}
 {"key1": 1,"keyset": [10, 20]}
(2 ROWS)

测试规划者是否可以使用索引:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SET enable_seqscan TO off;

EXPLAIN analyse
SELECT jsondata
FROM test
WHERE jsondata->'keyset' @> '10'

                                                     QUERY PLAN                                                    
--------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan ON test  (cost=8.00..12.02 ROWS=1 width=55) (actual TIME=0.024..0.025 ROWS=2 loops=1)
   Recheck Cond: ((jsondata -> 'keyset'::text) @> '10'::jsonb)
   Heap Blocks: exact=1
   ->  Bitmap INDEX Scan ON test_keyset  (cost=0.00..8.00 ROWS=1 width=0) (actual TIME=0.014..0.014 ROWS=2 loops=1)
         INDEX Cond: ((jsondata -> 'keyset'::text) @> '10'::jsonb)
 Planning TIME: 0.576 ms
 Execution TIME: 0.066 ms
(7 ROWS)