GIN 索引提速全文与多值查询
GIN 索引从复合值中提取可搜索的键,并记录这些键对应哪些行。全文文档、数组和 JSONB 都可以使用这种访问方法,但每个索引表达式仍需要匹配的操作符类。GIN 提供的是一组支持特定谓词的搜索能力,不是一建就能自动加速所有字段、类型和查询条件的万能索引。评估它之前,必须先明确应用到底怎样查找数据。 索引的是搜索表示 全文搜索中,to_tsvector 把正文转换成规范化词项,tsquery 描述要匹配的条件。建在这个向量上的 GIN 可以先缩小候选行集合,避免每次请求都解析全部文档。但是常见词仍可能对应很大的候选集合,后续读取行、复查条件、计算排名和排序都可能成为主要开销。索引查得快,并不代表整个搜索页面一定快,更不意味着返回所有匹配项没有成本。 文本配置本身属于查询语义。English 配置可能把 “outage” 词干化成不同于 simple 配置的词项,所以建立在 to_tsvector('english', body) 上的表达式索引,需要查询使用匹配的表达式。省略配置会让转换依赖会话设置,也不会匹配这个显式 English 索引。两参数形式还保证索引中的转换不随默认配置漂移,否则相同正文可能在不同时间产生不同词项。 其他 GIN 用法使用不同操作符。JSONB 的默认操作符类与 path 操作符类支持的条件并不完全相同,数组包含索引也不是全文索引。应根据真实谓词选择列、表达式和操作符类,而不是看到一种数据类型支持 GIN 就直接添加。如果应用查询不兼容,索引仍消耗存储和写入资源,却无法带来读收益;这种情况比没有索引更容易给人错误信心。 待处理条目仍可搜索 一篇文档可能贡献许多键,所以维护倒排结构的写入工作量较大。启用 fastupdate 时,新条目可以先进入 pending list,再合并到主索引结构。查询会同时搜索待处理列表和主结构,因此它调整的是维护工作的时机及额外查询成本,不是用延迟可见性换写入速度。当前快照中可见的新行,在列表清理之前也必须能够被查到。 VACUUM、自动 ANALYZE、显式清理函数或列表超过阈值,都可能触发合并。列表过大会拖慢搜索,前台写入碰上清理周期也可能出现延迟尖峰。增大阈值只是改变什么时候付出成本,并没有消除维护工作。调整前应结合导入速度、查询延迟、自动维护行为和维护窗口评估,不能把某个配置值当成对所有业务都适用的答案。 坏掉的样子 常见回归是应用重构后改了文本配置或表达式,查询仍返回正确结果,却失去了原先预期的访问路径。检查 EXPLAIN 中实际使用的条件和索引,先确认语义一致,再讨论规划器选择。小表采用顺序扫描本身并不能证明配置错误;但 simple 表达式确实不能拿 English 表达式索引当成相同语义使用,强行关闭顺序扫描也不会修正这种不匹配。 ...