执行查询命令(动态sql)比普通查询运行得更快

时间:2013-08-13 19:01:23

标签: sql sql-server database-performance

为什么使用EXECUTE命令的第二个查询运行速度比没有一个查询的第一个查询快4倍?我该如何解决这个问题?

为什么在第二种情况下创建附加表(Workatable)?

变量:

DECLARE @count INT, @followerId BIGINT
SET @count=1024
SET @followerId=10

首次查询(常用查询):

SELECT TOP (@count) Photo.* FROM Photo
WHERE  EXISTS (SELECT accountId FROM Follower
WHERE Follower.followerId=@followerId
AND Follower.accountId = Photo.accountId) 
AND Photo.closed='False'
ORDER BY Photo.createDate DESC

日志:

SQL Server解析和编译时间:CPU时间= 0毫秒,已用时间= 7毫秒。

SQL Server执行时间:CPU时间= 0 ms,已用时间= 0 ms。

表'照片'。扫描计数952,逻辑读取542435,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

表'追随者'。扫描计数1,逻辑读取7,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

SQL Server执行时间:CPU时间= 1466毫秒,已用时间= 9620毫秒

执行计划:

First query execution plan

第二次查询(与EXECUTE相同的查询):

EXEC ('SELECT TOP (' +@count + ') Photo.* FROM Photo
WHERE  EXISTS ( SELECT  accountId FROM Follower
WHERE Follower.followerId=' +@followerId + '
AND Follower.accountId = Photo.accountId) 
AND Photo.closed=''False''
ORDER BY Photo.createDate DESC')

日志:

SQL Server解析和编译时间:CPU时间= 0 ms,已用时间= 0 ms。

SQL Server执行时间:CPU时间= 0 ms,已用时间= 0 ms。

SQL Server执行时间:CPU时间= 0毫秒,已用时间= 0毫秒。 SQL Server解析和编译时间:CPU时间= 25毫秒,已用时间= 25毫秒。

表'工作台'。扫描计数0,逻辑读取0,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

表'照片'。扫描计数952,逻辑读取542707,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

表'追随者'。扫描计数6,逻辑读取9,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

表'工作台'。扫描计数0,逻辑读取0,物理读取0,预读取读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。

SQL Server执行时间:CPU时间= 1374毫秒,已用时间= 2140毫秒。

SQL Server执行时间:CPU时间= 1405毫秒,已用时间= 2165毫秒

1 个答案:

答案 0 :(得分:3)

这可能是因为第二个查询(取决于第一个查询的上下文)更可优化,因为变量变为内联常量。比较:

DECLARE @count INT, @followerId BIGINT
SET @count=1024
SET @followerId=10

SELECT TOP (@count) Photo.* FROM Photo
WHERE  EXISTS (SELECT accountId FROM Follower
WHERE Follower.followerId=@followerId
AND Follower.accountId = Photo.accountId) 
AND Photo.closed='False'
ORDER BY Photo.createDate DESC

使用:

SELECT TOP (1024) Photo.* FROM Photo
WHERE  EXISTS (SELECT accountId FROM Follower
WHERE Follower.followerId=10
AND Follower.accountId = Photo.accountId) 
AND Photo.closed='False'
ORDER BY Photo.createDate DESC

如果您的第一个查询是存储过程的一部分,变量是参数,并且在编译存储过程时使用不同的参数值优化了特定查询,则尤其如此。