我有一个 Postgres 表,mytable其中一个字段如下:
myField JSONB[] NOT NULL
让我们假设上述 jsons 是这种形式:
{ "letter":"A", "digit":30}
我应该使用哪些查询:
digit值?digit值的 json 数组?digit值的数组在哪里digit > 20?digit值的 json 数组在哪里digit > 20?如果我将数据存储为 json ,其中 json 是一个列表,上述查询将如何改变?
让我们创建一个表,其中包含一个jsonb[]名为类型的列pg_array将存储数组 JSON 对象,以及一个jsonb名为类型的列json_array将存储一个 JSON 对象数组:
CREATE TABLE mytable (id int, pg_array jsonb[], json_array jsonb);
INSERT INTO mytable VALUES
(1, ARRAY['{"letter":"A", "digit":30}', '{"letter":"B", "digit":31}']::jsonb[], '[{"letter":"A", "digit":30},{"letter":"B", "digit":31}]'),
(2, ARRAY['{"letter":"X", "digit":40}', '{"letter":"Y", "digit":41}']::jsonb[], '[{"letter":"X", "digit":40},{"letter":"Y", "digit":41}]');
Run Code Online (Sandbox Code Playgroud)
这两种方法的查询看起来非常相似,因为我们将处理单个数组元素,这意味着我们必须再次取消嵌套和聚合。
要取消嵌套pg_array并获取每个jsonb对象:
SELECT unnest(pg_array);
Run Code Online (Sandbox Code Playgroud)
要取消嵌套json_array并获取每个jsonb对象:
SELECT jsonb_array_elements(json_array);
Run Code Online (Sandbox Code Playgroud)
这是唯一的区别。因此,下面的查询看起来几乎相同。
关于你的第一组问题:
提取数字值的数组?
db=# SELECT array_agg((x->>'digit')::int) FROM mytable, unnest(pg_array) x GROUP BY id;
array_agg
-----------
{40,41}
{30,31}
(2 rows)
Run Code Online (Sandbox Code Playgroud)
db=# SELECT array_agg((x->>'digit')::int) FROM mytable, jsonb_array_elements(json_array) x GROUP BY id;
array_agg
-----------
{40,41}
{30,31}
(2 rows)
Run Code Online (Sandbox Code Playgroud)
提取一个包含数字值的 json 数组?
db=# SELECT jsonb_agg((x->>'digit')::int) FROM mytable, unnest(pg_array) x GROUP BY id;
jsonb_agg
-----------
[40, 41]
[30, 31]
(2 rows)
Run Code Online (Sandbox Code Playgroud)
db=# SELECT jsonb_agg((x->>'digit')::int) FROM mytable, jsonb_array_elements(json_array) x GROUP BY id;
jsonb_agg
-----------
[40, 41]
[30, 31]
(2 rows)
Run Code Online (Sandbox Code Playgroud)
提取数字值的数组,其中数字> 20?
(我在这里使用了 30 而不是 20。)
db=# SELECT array_agg((x->>'digit')::int) FROM mytable, unnest(pg_array) x WHERE (x->>'digit')::int > 30 GROUP BY id;
array_agg
-----------
{40,41}
{31}
(2 rows)
Run Code Online (Sandbox Code Playgroud)
db=# SELECT array_agg((x->>'digit')::int) FROM mytable, jsonb_array_elements(json_array) x WHERE (x->>'digit')::int > 30 GROUP BY id;
array_agg
-----------
{40,41}
{31}
(2 rows)
Run Code Online (Sandbox Code Playgroud)
提取数字值的json数组,其中数字> 20?
(我在这里使用了 30 而不是 20。)
db=# SELECT jsonb_agg((x->>'digit')::int) FROM mytable, unnest(pg_array) x WHERE (x->>'digit')::int > 30 GROUP BY id;
jsonb_agg
-----------
[40, 41]
[31]
(2 rows)
Run Code Online (Sandbox Code Playgroud)
db=# SELECT jsonb_agg((x->>'digit')::int) FROM mytable, jsonb_array_elements(json_array) x WHERE (x->>'digit')::int > 30 GROUP BY id;
jsonb_agg
-----------
[40, 41]
[31]
(2 rows)
Run Code Online (Sandbox Code Playgroud)
对于您的第二组问题:
我还可以进行上述所有查询吗?
如上所示,是的。
性能差异是什么?
这归结为unnest和的性能差异jsonb_array_elements。让我们将其与包含具有 1,000,000 个 JSON 对象的数组的单行进行比较:
db=# SELECT array_agg((x->>'digit')::int) FROM mytable, unnest(pg_array) x GROUP BY id;
array_agg
-----------
{40,41}
{30,31}
(2 rows)
Run Code Online (Sandbox Code Playgroud)
phil=# EXPLAIN ANALYZE SELECT unnest(pg_array) FROM mytable;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------
ProjectSet (cost=0.00..35.88 rows=5000 width=32) (actual time=33.357..120.393 rows=1000000 loops=1)
-> Seq Scan on mytable (cost=0.00..10.50 rows=50 width=626) (actual time=0.010..0.013 rows=1 loops=1)
Planning time: 0.050 ms
Execution time: 175.670 ms
(4 rows)
phil=# EXPLAIN ANALYZE SELECT jsonb_array_elements(json_array) FROM mytable;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------
ProjectSet (cost=0.00..35.88 rows=5000 width=32) (actual time=257.313..399.883 rows=1000000 loops=1)
-> Seq Scan on mytable (cost=0.00..10.50 rows=50 width=721) (actual time=0.010..0.014 rows=1 loops=1)
Planning time: 0.047 ms
Execution time: 455.275 ms
(4 rows)
Run Code Online (Sandbox Code Playgroud)
由此看来,它unnest比 快 2.5 倍左右jsonb_array_elements。
我什么时候应该选择一个?
我假设您的数据集不够大unnest,jsonb_array_elements无法发挥作用之间的性能差异。因此,我只会选择在数据方面更有意义的内容。我倾向于使用jsonb[]它,因为它更清楚地表明您将拥有一组 json 对象。
| 归档时间: |
|
| 查看次数: |
894 次 |
| 最近记录: |