SQLServer inner join 不先执行where条件的优化

前端操作偶尔超时,发现一个查询很慢,格式如下:

select * from a 
inner join b on b.id=a.bid
inner join c on c.id=a.cid
where a.way=1 and a.num='10000'


a 表为深红色,返回240万行数据。执行了33秒。最终结果返回一条记录!可以看到其行数估计非常不准。



看看该索引统计信息最后更新时间,是2014-12更新的。

更新整个表的统计信息:UPDATE STATISTICS DBO.TableName

更新之后再执行,结果还是一样,看来统计信息没有错。



可能大家会想到的,是先这样执行过滤。即时这样执行,优化引擎选择还是一样的。

select * 
from (select * from a where way=1 and num='10000')a 
inner join b on b.id=a.bid
inner join c on c.id=a.cid


再看上图,深红色的为a表,a表先和b表连接,生成大量数据,b表再键查找过滤条件。


现在的优化目标是: a表是先过滤条件(返回只有1行记录),再与b进行关联。


有3种处理方案:

1 . 强制使用嵌套(哈希、合并)连接

2. 使用左连接

3. 更改索引



测试:

1 . 强制使用嵌套(哈希、合并)连接

在测试这种方案时,是用了另一个测试环境,不过执行计划一样。

可以使用loop、hash、merge 连接。hash、merge消耗内存较多,所以使用了loop。

select * from a 
inner loop join b on b.id=a.bid
inner join c on c.id=a.cid
where a.way=1 and a.num='10000'

2. 使用左连接。因为只有一条记录,不改变查询结果,可以用。 

select * from a 
left join b on b.id=a.bid
left join c on c.id=a.cid
where a.way=1 and a.num='10000'

3. 更改索引

当前a表的索引为  ix_a(id,bid) , ix_a_num(num)

连接时,肯定首先连接的索引 ix_a(id,bid),该索引并未包括查询条件中的列。

可以重建新的索引如:ix_a(id,bid,num,way)



最后使用了第二种方法。前2种方法执行都3秒以下或不到一秒。第3种方法要改索引,就不必了。

执行结果如下图:深红色的a表可以先过滤条件再关联其他表了!





评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值