PostgreSQL 中的多列 GIN 索引不会对 `preference` jsonb 列执行索引扫描

问题描述 投票:0回答:1

我有一个

preference
列,其类型为
JSONB
。 JSON 的结构如下所示

{
    "slotStatus": {
        "reason": "Weather",
        "status": "CANCELLED",
        "statusMeta": "RE"
    },
    "registration": {
        "restriction": "perEvent",
        "maxRegistration": 20
    }
}

我创建了一个多列GIN索引

CREATE INDEX mv_view_eventid_preference_idx
    ON mv_view using GIN (event_id, preference)

当我执行以下查询的

Explain analyze
时,仅扫描
event_id
。但
status
列内的
preference
字段未进行索引扫描。这会导致检索大约 50k 条记录的执行时间更长(大约 45 到 50 秒)。

Explain analyze SELECT s.preference, s.data FROM mv_view s WHERE 
    s.event_id= 'event id goes here' AND (
    NOT (s.preference::jsonb -> 'slotStatus' @> '{"status": "CANCELLED"}')
    OR s.preference::jsonb -> 'slotStatus' IS NULL

此表上的索引:

CREATE INDEX loc_slot_mv_view_eventid_preference_idx
    ON mv_view USING gin
    (event_id, preference)
    TABLESPACE pg_default;


CREATE UNIQUE INDEX loc_slot_mv_view_slotid_idx
    ON mv_view USING btree
    (id)
    TABLESPACE pg_default;

您能否协助完善查询,以确保

event_id
列中的
status
preference
字段在必要时都经过索引扫描?

解释(分析)

解释(分析,详细):

解释(分析、缓冲区):

解释(分析、设置):

postgresql jsonb
1个回答
0
投票

索引仅适用于已索引的事物。索引的东西是“偏好”这一列,而不是表达式

prefence::jsonb -> 'slotStatus'
,所以不能使用索引。

此外,你甚至没有使用

@>
,你正在使用
NOT ... @>
。无论如何都无法索引。

最后,即使前两个没有,OR 也会阻止索引的使用。

第一个可以通过更改查询或更改索引来规避,但我认为你无法绕过第二个,所以你几乎陷入困境。

© www.soinside.com 2019 - 2024. All rights reserved.