【发布时间】:2020-05-03 06:15:37
【问题描述】:
我们正在为我们的一个项目更改 DB(PostgreSQL 10.11) 结构。其中一项更改是将 uuid[] 类型的字段(称为“areasoflawid”)移动到 jsonb 字段(称为“数据”)中。
所以,我们有一个如下所示的表格:
CREATE TABLE public.documents
(
id serial,
areasoflawid uuid[], --the field to be moved into the ‘data’
data jsonb,
….
)
我们不会更改数组的值或其结构。 即documents.data->'metadata'->'areaoflawids'包含与documents.areasoflawid相同的项目) 数据迁移后,“data”字段中存储的JSON结构如下:
{
...
"metadata": {
...
"areaoflawids": [
"e34e0ee5-78e0-4d92-9186-ac69c109408b",
"b3af9163-d910-4d19-8f40-0602b75c25b0",
"50dc7fd8-ebdf-4cd2-bcab-b8d755fe96e8",
"8955c062-363f-4a1a-ac3c-d1c2ffe96c9b",
"bdb79f9f-4539-45f5-ac82-92baaf915f6c"
],
....
},
...
}
因此,在迁移数据之后,我们开始对 jsonb 字段相关的查询进行基准测试,并发现搜索数组字段documents.data->'metadata'->'areaoflawids' 比搜索uuid[] 字段documents.areasoflawid 花费的时间要长得多.
这里是查询:
--search over jsonb array field, takes 6.2 sec, returns 13615 rows
SELECT id FROM documents WHERE data->'metadata'->'areaoflawids' @> '"e34e0ee5-78e0-4d92-9186-ac69c109408b"'
--search over uuid[] field, takes 600ms, returns 13615 rows
SELECT id FROM documents WHERE areasoflawid @> ARRAY['e34e0ee5-78e0-4d92-9186-ac69c109408b']::uuid[]
这是 jsonb 字段的索引:
CREATE INDEX test_documents_aols_gin_idx
ON public.documents
USING gin
(((data -> 'metadata'::text) -> 'areaoflawids'::text) jsonb_path_ops);
这是执行计划:
EXPLAIN ANALYZE SELECT id FROM documents WHERE data->'metadata'->'areaoflawids' @> '"e34e0ee5-78e0-4d92-9186-ac69c109408b"'
"Bitmap Heap Scan on documents (cost=6.31..390.78 rows=201 width=4) (actual time=2.297..5859.886 rows=13614 loops=1)"
" Recheck Cond: (((data -> 'metadata'::text) -> 'areaoflawids'::text) @> '"e34e0ee5-78e0-4d92-9186-ac69c109408b"'::jsonb)"
" Heap Blocks: exact=4859"
" -> Bitmap Index Scan on test_documents_aols_gin_idx (cost=0.00..6.30 rows=201 width=0) (actual time=1.608..1.608 rows=13614 loops=1)"
" Index Cond: (((data -> 'metadata'::text) -> 'areaoflawids'::text) @> '"e34e0ee5-78e0-4d92-9186-ac69c109408b"'::jsonb)"
"Planning time: 0.133 ms"
"Execution time: 5862.807 ms"
对 jsonb 字段的其他查询以可接受的速度工作,但这种特定的搜索比在分隔字段上的搜索慢约 10 倍。我们期望它会慢一点,但还不错。我们考虑将这个“areasoflawid”字段作为一个单独的字段保留的选项,但我们肯定更愿意将它移动到 json 中。我一直在使用不同的索引和操作(也使用?和?|),但搜索仍然很慢。任何帮助表示赞赏!
【问题讨论】:
-
你试过
WHERE data->'metadata'->'areaoflawids' ? 'e34e0ee5-78e0-4d92-9186-ac69c109408b' -
嗨,是的,它对我没有多大帮助...要使用此操作,我必须更改索引:``` CREATE INDEX test_documents_aols_gin_idx ON public.documents USING gin (((data -> '元数据'::text) -> 'areaoflawids'::text)); ``` 所以查询执行相同 - 6.0sec ``` SELECT id FROM documents WHERE data->'metadata'->'areaoflawids' ? 'e34e0ee5-78e0-4d92-9186-ac69c109408b'; ``` 执行计划看起来一样:
-
您能否为此查询显示
EXPLAIN (ANALYZE, BUFFERS),以及您要与之比较的其他查询?
标签: arrays postgresql indexing jsonb