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

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

select * from a inner join b on b.id=a.bidinner join c on c.id=a.cidwhere 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.bidinner 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.bidinner join c on c.id=a.cidwhere a.way=1 and a.num='10000'2. 使用左连接。因为只有一条记录,不改变查询结果,可以用。select * from a left join b on b.id=a.bidleft join c on c.id=a.cidwhere 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表可以先过滤条件再关联其他表了!

人生的大部份时间里,承诺同义词是束缚,奈何我们向往束缚。

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

相关文章:

你感兴趣的文章:

标签云: