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表可以先过滤条件再关联其他表了! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |