为什么 PostgreSQL 在 Merge Join 场景中不使用索引?

Why isn't PostgreSQL using an index in a Merge Join scenario?

explain select count(1) from tab1_201502 t1, tab2_201502 t2
            where t1.serv_no=t2.serv_no
                and t1.PC_LOGIN_COUNT1 >5
                    and t1.FET_WZ_FEE < 80
                        and t2.ALL_FLOW_2G<50;

                                QUERY PLAN                                                      
----------------------------------------------------------------------
 Aggregate  (cost=4358706.25..4358706.26 rows=1 width=0)
   ->  Merge Join  (cost=4339930.99..4358703.30 rows=1179 width=0)
         Merge Cond: ((t1.serv_no)::text = (t2.serv_no)::text)
         ->  Index Scan using tab1_201502_serv_no_idx on tab1_201502 t1
              (cost=0.56..6239071.57 rows=263219 width=12)
               Filter: ((pc_login_count1 > 5::numeric)
                        AND (fet_wz_fee < 80::numeric))
         ->  Sort  (cost=4339914.76..4340306.63 rows=156747 width=12)
               Sort Key: t2.serv_no
               ->  Seq Scan on tab2_201502 t2
                    (cost=0.00..4326389.00 rows=156747 width=12)
                     Filter: (all_flow_2g < 50::numeric)

所有表都在 serv_no 上建立了索引。

为什么 PostgreSQL 忽略 tab2_201502 索引进行扫描?

这是您的查询:

select count(1)
from tab1_201502 t1 join
     tab2_201502 t2 
     on t1.serv_no = t2.serv_no 
where t1.PC_LOGIN_COUNT1 > 5 and t1.FET_WZ_FEE < 80 and t2.ALL_FLOW_2G < 50; 

Postgres 决定通过 where 子句过滤比执行 join.

更重要

我建议为此查询尝试两组索引。它们是:tab2_201502(ALL_FLOW_2G, serv_no)tab1_201502(serv_no, PC_LOGIN_COUNT1, FET_WZ_FEE).

第二对是:tab1_201502(PC_LOGIN_COUNT1, FET_WZ_FEE, serv_no)tab2_201502(serv_no, ALL_FLOW_2G)

哪个效果更好取决于 table 是 join 的驱动 table。