postgresql 第二位置的限制-未使用索引-为什么?

bwitn5fc  于 2023-02-12  发布在  PostgreSQL
关注(0)|答案(1)|浏览(113)

我创建了下面的例子,但不明白为什么计划员不使用索引i2进行查询。它知道列uniqueIds包含唯一的值,也知道列fourOtherIds只包含4个不同的值,那么搜索索引i2不是最快的方法吗?只在fourOtherIds的四个不同索引叶中查找uniqueIds?我对索引工作原理的理解有什么问题?为什么它认为使用i1在这里更有意义,即使它必须过滤掉333.333行?在我的理解中,它应该使用i2来查找一行(或很少的行,因为没有唯一约束),其首先具有uniqueIds 4000,然后应用where fourIds = 1作为过滤器。

create table t (fourIds int, uniqueIds int,fourOtherIds int);
insert into t ( select 1,*,5 from generate_series(1      ,1000000));
insert into t ( select 2,*,6 from generate_series(1000001,2000000));
insert into t ( select 3,*,7 from generate_series(2000001,3000000));
insert into t ( select 4,*,8 from generate_series(3000001,4000000));
create index i1 on t (fourIds);
create index i2 on t (fourOtherIds,uniqueIds);
analyze t;
select n_distinct,attname from pg_stats where tablename = 't';
/* 
n_distinct|attname     |
----------+------------+
       4.0|fourids     |
      -1.0|uniqueids   |
       4.0|fourotherids|
*/
explain analyze select * from t where fourIds = 1 and uniqueIds = 4000;
/*
QUERY PLAN                                                                                                                |
--------------------------------------------------------------------------------------------------------------------------+
Gather  (cost=1000.43..22599.09 rows=1 width=12) (actual time=0.667..46.818 rows=1 loops=1)                               |
  Workers Planned: 2                                                                                                      |
  Workers Launched: 2                                                                                                     |
  ->  Parallel Index Scan using i1 on t  (cost=0.43..21598.99 rows=1 width=12) (actual time=25.227..39.852 rows=0 loops=3)|
        Index Cond: (fourids = 1)                                                                                         |
        Filter: (uniqueids = 4000)                                                                                        |
        Rows Removed by Filter: 333333                                                                                    |
Planning Time: 0.107 ms                                                                                                   |
Execution Time: 46.859 ms                                                                                                 |
*/
5t7ly7z5

5t7ly7z51#

并不是所有的优化都已经实现了,你正在寻找一个index skip scan的变体,也就是一个松散的索引扫描,PostgreSQL不会自动实现这些(然而--人们正在研究它,但我不知道他们是否还在研究。另外,我想我读到过第三方扩展/分支之一,可能是citus,已经实现了它)。您可以使用递归CTE自己模拟一个扩展a分支,但那样做会很烦人。

相关问题