是jsonb_column @> '{"key":value}'::jsonb运营商等于jsonb_column->'key' = value?在将使用的结果、性能和索引方面?
dez*_*zso 13
我创建了一个小测试来检查这个:
CREATE TABLE jsonb_test (id serial, data jsonb);
Run Code Online (Sandbox Code Playgroud)
然后插入一些生成的数据:
INSERT INTO jsonb_test (data)
SELECT row_to_json(x.*)::jsonb
FROM (SELECT i AS bla,
ARRAY[i, i+1, i+2] AS foo,
ARRAY[('v' || i::text, i), ('v' || (i * 10)::text, i)] AS bar
FROM generate_series(1,100000) t(i)
) x;
Run Code Online (Sandbox Code Playgroud)
让我们在那里找到一些东西(版本 1):
SELECT * FROM jsonb_test WHERE data @> '{"bla": 545}'::jsonb;
Run Code Online (Sandbox Code Playgroud)
执行计划看起来像
Seq Scan on jsonb_test (cost=0.00..7604.89 rows=369 width=36) (actual time=0.425..47.600 rows=1 loops=1)
Filter: (data @> '{"bla": 545}'::jsonb)
Rows Removed by Filter: 99999
Buffers: shared hit=2997 dirtied=676
Planning time: 0.078 ms
Execution time: 47.692 ms
Run Code Online (Sandbox Code Playgroud)
如果我对您提议的其他版本(版本 2)也这样做(操作员从->更改->>为 我认为您的意思):
SELECT * FROM jsonb_test WHERE data ->> 'bla' = '545';
Run Code Online (Sandbox Code Playgroud)
我有一个计划
Seq Scan on jsonb_test (cost=0.00..8526.47 rows=1843 width=36) (actual time=0.613..34.657 rows=1 loops=1)
Filter: ((data ->> 'bla'::text) = '545'::text)
Rows Removed by Filter: 99999
Buffers: shared hit=2997
Planning time: 0.116 ms
Execution time: 34.727 ms
Run Code Online (Sandbox Code Playgroud)
反复运行它们,我发现执行时间之间没有显着差异。难怪 - 这里昂贵的操作是顺序扫描,而两种不同的过滤条件在这方面应该差别不大。
现在我添加了一个 GIN 索引data:
CREATE INDEX ON jsonb_test USING gin (data);
Run Code Online (Sandbox Code Playgroud)
现在执行查询时,版本 2与上述相同,而版本 1有一个新计划:
Bitmap Heap Scan on jsonb_test (cost=28.77..372.05 rows=100 width=36) (actual time=0.081..0.083 rows=1 loops=1)
Recheck Cond: (data @> '{"bla": 545}'::jsonb)
Rows Removed by Index Recheck: 2
Heap Blocks: exact=1
Buffers: shared hit=10
-> Bitmap Index Scan on jsonb_test_data_idx (cost=0.00..28.75 rows=100 width=0) (actual time=0.062..0.062 rows=3 loops=1)
Index Cond: (data @> '{"bla": 545}'::jsonb)
Buffers: shared hit=9
Planning time: 0.084 ms
Execution time: 0.122 ms
Run Code Online (Sandbox Code Playgroud)
这已经表明这两个版本并不完全等效 -jsonb列上的 GIN 索引仅支持其中之一(版本 1)。
可以定义另一个索引来帮助版本 2:
CREATE INDEX ON jsonb_test ((data->>'bla'));
Run Code Online (Sandbox Code Playgroud)
现在版本 2给出了以下内容:
Bitmap Heap Scan on jsonb_test (cost=12.17..1323.49 rows=500 width=36) (actual time=0.065..0.070 rows=1 loops=1)
Recheck Cond: ((data ->> 'bla'::text) = '545'::text)
Heap Blocks: exact=1
Buffers: shared hit=1 read=2
-> Bitmap Index Scan on jsonb_test_expr_idx (cost=0.00..12.04 rows=500 width=0) (actual time=0.046..0.046 rows=1 loops=1)
Index Cond: ((data ->> 'bla'::text) = '545'::text)
Buffers: shared read=2
Planning time: 0.480 ms
Execution time: 0.133 ms
Run Code Online (Sandbox Code Playgroud)
在这个实验中,如果索引正确,我没有看到两者之间的巨大性能差异。但是,您应该考虑以下几点:
由于可能为每个项目插入许多键,因此插入 GIN 索引可能会很慢。因此,对于表中的批量插入,建议删除 GIN 索引并在完成批量插入后重新创建它。
通常说 BTree 索引比 GIN 索引维护成本更低(意味着表上的数据更改具有更小的开销)。通过阅读,情况并非总是如此 - 您必须在自己的数据集上测试这些解决方案。例如,我无法判断一组非常复杂的jsonb值是否更喜欢这个或那个。
笔记:
json(b)运营商的异同,官方文档是一个很好的来源。| 归档时间: |
|
| 查看次数: |
2310 次 |
| 最近记录: |