如果存在多个索引,Postgres 如何选择使用哪个索引?

Posted

技术标签:

【中文标题】如果存在多个索引,Postgres 如何选择使用哪个索引?【英文标题】:How does Postgres choos which index to use in case if multiple indexes are present? 【发布时间】:2020-10-15 07:33:42 【问题描述】:

我是 Postgres 的新手,如果我有多个如下定义的 btree 索引,我对 Postgres 如何决定使用哪个索引有点困惑。

CREATE INDEX index_1 ON sample_table USING btree (col1, col2, COALESCE(col3, 'col3'::text));

CREATE INDEX index_2 ON sample_table USING btree (col1, COALESCE(col3, 'col3'::text));

当我写入 sample_table(来自源表)时,我在联接条件中使用 col1, col2, COALESCE(col3, 'col3'::text) 但是当我进行解释分析以获取查询计划时,我有时会看到它使用 index_2 而不是 index_1 进行扫描,有时只使用顺序扫描。我想了解什么可以使 Postgres 使用一个索引而不是另一个索引?

【问题讨论】:

简而言之:优化器评估不同的策略并为每个策略分配一个成本值。然后选择成本最低的那个。有关更多说明,请参阅Using EXPLAIN 感谢@a_horse_with_no_name,您的解释 【参考方案1】:

没有看到EXPLAIN (ANALYZE, BUFFERS)的输出,我只能给出一个笼统的答案。

PostgreSQL 考虑所有可行的执行计划并估计每个节点的行数和成本。然后采用成本估算最低的方案。

可能是col2 上的条件有时更具选择性,有时则更少,例如因为您有时将其与稀有值进行比较,有时与频繁值进行比较。如果涉及col2 的条件不是选择性的,那么使用这两个索引中的哪一个并不重要。在这种情况下,PostgreSQL 更喜欢较小的两列索引。

【讨论】:

非常感谢@Laurenz Albe 的解释,关于同一行的另一个问题,postgres sql 是否可以强制/提示使用索引,如果可能的话,这样做是个好主意吗? 不,这是不可能的。只要查询有效执行,使用的索引应该无关紧要。考虑删除其中一项索引以获得更高的计划稳定性、更短的计划时间和更有效的数据修改。

以上是关于如果存在多个索引,Postgres 如何选择使用哪个索引?的主要内容,如果未能解决你的问题,请参考以下文章

索引扫描时 Postgres 不使用索引是更好的选择

如何参数化 Postgres-custom-function 中的表和列,如果值存在则选择 PK,否则插入并返回 PK?

在 Postgres 的单个索引中包含多个列

如何使用 Postgres jsonb '? Laravel 中具有索引支持的运算符?

如果我删除带有索引的 PG 表,该索引是不是仍然存在?

Python 数据处理(二十四)—— 索引和选择