为何PostgreSQL在比较值来自自定义函数时不完整使用索引?
索引列与查询条件的匹配逻辑不兼容
你创建的复合索引individual_profile_identity_name_birth_dt_doc_idx是基于表中原始的normalized_name(带varchar_pattern_ops)、birth_date、normalized_document_number字段构建的,但查询时你用自定义函数rf_normalize_name生成的值来和这些字段做比较。这种写法相当于在索引列上套了一层函数转换,PostgreSQL无法直接将这类条件与索引的有序存储结构匹配,自然没法用索引来加速这部分条件的筛选。自定义函数的属性与索引要求不匹配
除非你专门创建基于rf_normalize_name函数的函数索引,否则现有复合索引无法适配这种带函数的查询条件。另外,如果rf_normalize_name没有被标记为IMMUTABLE(即相同输入必然返回相同输出),PostgreSQL优化器会认为函数结果可能不稳定,不会将其作为索引扫描的依据——毕竟索引是基于固定值构建的,不能依赖可能变化的函数结果。复合索引的左前缀匹配规则限制
复合索引遵循左前缀匹配原则,你的索引顺序是normalized_name优先,其次是birth_date,最后是normalized_document_number。当查询无法利用第一个索引列的条件触发索引扫描时,优化器只能跳过前面的列,尝试匹配后续的birth_date列,这就导致只有birth_date被用作索引条件,剩下的条件只能在索引扫描完成后作为过滤器执行。
内容的提问来源于stack exchange,提问作者Eduard Grigoryev

