postgresql where子句中有多个索引,Postgres选择哪一个?

k2fxgqgv  于 2022-11-04  发布在  PostgreSQL
关注(0)|答案(1)|浏览(120)

我有table

CREATE TABLE IF NOT EXISTS employeedb.employee_tbl
(
    id                         integer                  NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
    dm_company_id              integer                  NOT NULL,
    customer_employee_id       text                     NOT NULL),
    personal_mobile            text,
    CONSTRAINT employee_pkey PRIMARY KEY (id),
    CONSTRAINT employee_id_company_constraint UNIQUE (dm_company_id, customer_employee_id)

和索引上personal_移动的类

CREATE INDEX company_id_personal_mobile_index ON employeedb.employee_tbl (dm_company_id, personal_mobile COLLATE "C");

现在当我点击以下查询时

explain analyse select * from employeedb.employee_tbl where dm_company_id = 2011 and employee_tbl.personal_mobile like '+1%';

我总是看到使用employee_id_company_constraint索引。

Index Scan using employee_id_company_constraint on employee_tbl  (cost=0.14..8.16 rows=1 width=641) (actual time=0.056..0.093 rows=2 loops=1)
  Index Cond: (dm_company_id = 2011)
  Filter: (personal_mobile ~~ '+1%'::text)
  Rows Removed by Filter: 28
Planning Time: 0.951 ms
Execution Time: 0.173 ms

为什么Postgres不使用比employee_id_company_constraint更高效的company_id_personal_mobile_index来进行上述查询?

blmhpbnm

blmhpbnm1#

我们无法从您的计划中看到一条重要信息,即它 * 认为 * 筛选器将删除多少行。这些重要数据没有报告。
您可以执行此查询,以探查供需规划员认为正在进行的作业:

explain analyse select * from employeedb.employee_tbl where dm_company_id = 2011;

我们需要知道它期望从这个简化的查询中找到多少行,以及它实际找到多少行(但假定它实际找到30行,即找到的2行+从当前计划中筛选出的28行)。
如果它认为dm_company_id = 2011只匹配1行,那么使用更复杂的索引来决定是否使用该行是没有意义的(根据计划者当前的思维方式),只测试这一行并查看应该更快。
如果我的理论是正确的,那么问题就变成了,为什么它期望找到1行,而真实的的答案是30?也许你的统计数据已经过时了,也许发生了其他事情。ANALYZE应该修复第一个问题,第二个问题需要更多的研究--在我的理论得到证实并且ANALYZE无法纠正问题之前,这是不必要的。

相关问题