PostgreSQL内连接SQL优化:百万级表查询性能提升及替代写法
SQL查询优化方案及替代写法
优化思路
- 改用半连接逻辑:原查询用普通内连接会读取T2的匹配行并做关联,但你只需要T1中存在于T2的记录,半连接(如
EXISTS/IN)会直接判断T1的c是否在T2中存在,避免不必要的数据读取和重复匹配,大幅降低耗时。 - 验证索引有效性:虽然已给
c字段建索引,需确认:- T2的
c索引是否为单列索引(无需包含其他字段,因为只需要判断存在性); - 数据库统计信息是否更新(过时的统计信息会导致优化器选错执行计划,比如PostgreSQL执行
ANALYZE T2;,MySQL执行ANALYZE TABLE T2;); - 若
c字段存在大量NULL值,可考虑在索引中排除NULL,减少索引扫描范围。
- T2的
- 减少匹配次数:如果T2的
c字段存在大量重复值,先对T2的c去重再关联,避免T1的同一行被多次匹配。 - 调整驱动表:强制让小表T1作为驱动表(比如MySQL用
STRAIGHT_JOIN,PostgreSQL用/*+ LEADING(t1) */提示),减少外层循环次数。
替代写法
写法1:EXISTS半连接(推荐)
select t1.a, t1.b, t1.c from T1 t1 where exists ( select 1 from T2 t2 where t2.c = t1.c );
这种写法是数据库半连接优化的最优形式,优化器会直接用T2的c索引做存在性判断,无需读取T2的其他数据。
写法2:IN子查询
select t1.a, t1.b, t1.c from T1 t1 where t1.c in (select t2.c from T2 t2);
注意:如果T2的c字段存在NULL值,IN子查询会排除T1中c为NULL的行,和原内连接逻辑略有差异(原内连接中NULL不会匹配),需根据业务场景选择。
写法3:去重后关联
适合T2的c字段有大量重复值的场景:
select t1.a, t1.b, t1.c from T1 t1 inner join (select distinct c from T2) t2 on t1.c = t2.c;
通过distinct减少T2的匹配行数,降低关联的计算量。
内容的提问来源于stack exchange,提问作者rsudha
相关产品推荐
相关产品推荐

