这两天检查一条嵌套SQL语句,发觉非常耗时。形如:
| SELECT KeyId,COUNT(1) AS Num |
| FROM Table1 |
| WHERE 1=1 |
| AND CreateDate>='2007-09-21' |
| AND KeyId IN(SELECT KeyId FROM Table2 WHERE Id=1611) |
| GROUP BY KeyId |
究其原因,大约该SQL语句执行的步骤是从Table1中每拿出一条记录,都要执行
IN(SELECT KeyId FROM Table2 WHERE Id=1611) 一番
靠,数据库也太弱智了吧。学编译方法时就知道,编译器会自动优化代码,将一些计算从循环中提取出来,数据库怎么就不能先查找出
(SELECT KeyId FROM Table2 WHERE Id=1611)
的结果,然后再代入整条SQL语句中执行呢?
先是这样修改:
| SELECT a.KeyId,COUNT(1) AS Num |
| FROM Table1 a |
| , (SELECT KeyId FROM Table2 WHERE Id=1611) AS b |
| WHERE 1=1 |
| AND a.CreateDate>='2007-09-21' |
| AND a.KeyId=b.KeyId |
| GROUP BY a.KeyId |
结果发现没什么改进,有时甚至效果更坏。
把心一横,祭出临时表来:
| SELECT KeyId INTO t# FROM Table2 WHERE Id=1611; |
| SELECT a.KeyId,COUNT(1) AS Num |
| FROM Table1 a, t# AS b |
| WHERE 1=1 |
| AND a.CreateDate>='2007-09-21' |
| AND a.KeyId=b.KeyId |
| GROUP BY a.KeyId; |
| DROP TABLE #t; |
结果速度改善非常明显。不必担心并发操作时临时表会有冲突,说这个会话创建了一个t#,那个会话也创建了一个t#。临时表就好象局部变量,只在某个会话里有意义。
来源:http://blog.youkuaiyun.com/leftfist/archive/2007/09/30/1808253.aspx
本文探讨了一种耗时的嵌套SQL查询,并通过使用临时表显著提高了查询效率。原始查询在每次迭代时重复执行子查询,修改后的方案则预先计算子查询结果,避免了不必要的重复计算。
2437

被折叠的 条评论
为什么被折叠?



