我有一个
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
字段在必要时都经过索引扫描?
解释(分析)
解释(分析,详细):
索引仅适用于已索引的事物。索引的东西是“偏好”这一列,而不是表达式
prefence::jsonb -> 'slotStatus'
,所以不能使用索引。
此外,你甚至没有使用
@>
,你正在使用NOT ... @>
。无论如何都无法索引。
最后,即使前两个没有,OR 也会阻止索引的使用。
第一个可以通过更改查询或更改索引来规避,但我认为你无法绕过第二个,所以你几乎陷入困境。