一次子查询的优化实例

现象

有这么一张表:

create table test
(
     nodeId int,
     flowId int,
     other varchar(10),
     primary key (nodeid),
     key idx1 (flowId, nodeId)
)

现在执行这样一个SQL:

select nodeId, flowId from test 
where nodeId in (
select max(nodeId)
  from test
 where flowId in (...) group by flowId
)

这个SQL看起来就很难看,而且不易理解。这个表的记录大概是100万条,这个SQL执行时间超过600ms。

优化

优化的第一步就是看执行计划:

image.png

挺可怕的一个执行计划,id=1的表,即外层表竟然进行一次索引全扫描,这个等同于全表扫描了。

在这里我要说一句话,这句话在大部分条件下是成立的:

关系型数据库,怕的不是关联

那么我们改造一下这个SQL,将它改成一个关联的写法:

select a.flowId, a.nodeId
 from test a
 inner join 
 (select max(nodeId) from test where flowId in (...) group by flowId) b
 on a.nodeId = b.nodeId;

这个执行计划就变成了这样:

image.png

注意扫描行数,不过102行,而且type的类型也是很优秀的,至于效果,这是优化前:

image.png

这是优化后:

image.png

高下立判。

结语

其实子查询是一种自然的想法的具体实现,在非DBA写的SQL中很常见,因为逻辑上是无懈可击的。但是DBA至少应该具有集合计算的基本素质,在考虑数据库关联查询的时候首先要想到集合运算,然后是关系代数理论。

DBA确实不是一个简单的工作,数学也不能差。

你可能感兴趣的:(一次子查询的优化实例)