Postgres JSONB 搭配 GIN 做灵活查询
PostgreSQL 的 JSONB 列可以容纳形态不同的文档,但高效查询仍要求条件与索引有准确的对应关系。对整篇文档建立 GIN 索引,只能支持特定的 JSONB 算子,不能自动加速所有从文档提取字段的表达式。先确定数据类型和查询语义,再选择索引,才能避免建完索引却没有收益。 让算子与索引对应 包含条件 payload @> '{"status":"pending"}' 检查文档是否包含该键及对应的 JSON 字符串值。采用默认 jsonb_ops 操作符类时,整列 GIN 可以支持包含、顶层键存在判断,以及能够提取索引条件的 JSON 路径查询。索引保存可检索的组成部分;位图堆扫描仍可能访问表,并重新检查候选行,不能把它理解为完全不用回表。 payload->>'status' = 'pending' 则是在比较提取后的文本。payload 上的 GIN 并不是这个文本表达式的索引。对 (payload->>'status') 建立 B-tree 表达式索引,才与标量等值查询对应。如果很多查询需要对 status 排序、关联或施加约束,独立的有类型列可能更清楚,也能减少不断从灵活文档中推导字段的成本。 不能未经类型检查,就把所有文本条件改写成包含条件。JSON 数字和 JSON 字符串经过文本提取后可能得到相同文本,但包含算子会区分它们的 JSON 类型。只有数据约束保证相关前提时,改写才等价。应用应通过数据库驱动绑定参数,而不是把不可信输入拼接进 SQL 或 JSON 字符串;索引选择和输入处理需要分别正确。 ...