CREATE INDEX CONCURRENTLY idx_orders_attrs
ON orders USING gin (attrs);
SELECT id FROM orders
WHERE attrs @> jsonb_build_object('status','paid');
订单属性的包含查询单次要三秒,表上已经有 gin(attrs) 索引,EXPLAIN 却还是走 Seq Scan。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。
追下去是这么回事:条件写成 attrs->>’status’ 再比较,GIN 索引只认 @> 和 ? 这类包含运算,先取字段再比值走不上索引,等于白建,这种写法在 ORM 里很常见。
「PG JSONB 查询优化」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。监控和日志的时间要对上,时区不一致会多绕很大一圈。
临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。
处理上按这个顺序:把等值条件改写成 @> 的包含形式,再重新跑一遍看计划;确认索引类型是 gin,而不是建成了默认的 btree;看 EXPLAIN 里有没有出现位图索引扫描,而不是顺序扫。
确认没问题再收工,同一条查询改走位图索引扫描,耗时从三秒降到几十毫秒。
