sha*_*ker 10 postgresql index array json
我有一个table带有 JSONB 字段的表data,其中包含一个可变长度数组,例如
{"label": "xyz", "items": [ ... ]}
Run Code Online (Sandbox Code Playgroud)
我在"items"元素的长度上创建了一个索引:
CREATE INDEX n_items ON table ( JSONB_ARRAY_LENGTH(data->'items') )
Run Code Online (Sandbox Code Playgroud)
但是当我过滤时,当我尝试对其进行过滤时,我仍然会得到顺序扫描:
EXPLAIN ANALYZE SELECT COUNT(*) FROM table WHERE JSONB_ARRAY_LENGTH(table.data->'items') = 2;
QUERY PLAN
-----------------------------------------------------------------------------------------
Aggregate (cost=2565655.67..2565655.68 rows=1 width=8)
-> Seq Scan on table (cost=0.00..2535256.19 rows=12159794 width=8)
Filter: (jsonb_array_length((table.data -> 'items'::text)) = 2)
Planning time: 0.121 ms
Execution time: 482891.694 ms
Run Code Online (Sandbox Code Playgroud)
过滤大约需要 8 分钟!我在这里做错了什么,还是因为 PostgreSQL 没有保留 JSON(B) 对象的统计信息?应该可以将这个data专栏展平,但我想确定这是我在开始工作之前需要做的事情。
编辑:这些数组长度变化不大。目前数据中只有 4 个不同的值,我不希望有更多。在这种情况下,索引不是很有用,还是我可以通过其他方式改进过滤?
dez*_*zso 13
在不知道您的数据的情况下,我只能猜测您的索引的选择性很低(如果数组的长度变化不大,就会发生这种情况)。
克服这个问题的一个技巧可能是稍微更改查询并创建覆盖索引。为此,选择一NOT NULL列(例如,表的主键)进行计数,然后将此列包含在索引中:
CREATE INDEX n_items ON your_table (jsonb_array_length(data->'items'), id);
SELECT count(id)
FROM your_table
WHERE JSONB_ARRAY_LENGTH(table.data->'items') = 2;
Run Code Online (Sandbox Code Playgroud)
这有望变成仅索引扫描(我测试了这个省略jsonb部分,但您将能够判断它是否有效)。
| 归档时间: |
|
| 查看次数: |
14712 次 |
| 最近记录: |