为什么“IF EXISTS”在这种情况下比“COUNT(*)”慢得多?

时间:2013-08-19 07:49:53

标签: sql sql-server-2008 reporting-services

我正在创建一份关于SSRS 2008 R2的报告。只有在数据存在时才会发送此报告。起初,我尝试创建数据驱动的订阅,调用存储过程来检查视图是否有数据。如果是这样,它会将报告发送给定义的收件人。由于用户要求每10分钟检查一次视图,我设置了一个作业来在SQL Server代理上执行此数据驱动订阅的作业名称。但我发现订阅总是超时,即使直接选择视图只需要大约二十到三十秒。

然后我试着想出其他方式来满足这个要求。

我尝试的方法是在SQL Server上创建一个存储过程,以检查视图是否首先包含数据。如果是,它将运行为SSRS 2008 R2上的报告创建的订阅的作业名称。为了每10分钟检查一次视图,我在SQL Server Angent上每10分钟创建一个执行此SP的作业。

问题是为什么用“IF EXISTS”执行SP1需要大约20分钟,而用“COUNT(*)”执行SP2只需要20秒。我真的很困惑。
感谢您的回复。 :)

SP1:

IF EXISTS (SELECT TOP 1 * FROM VIEW)
BEGIN
EXEC msdb.dbo.sp_start_job
@job_name = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx'

END

--

IF EXISTS (SELECT TOP 1 C1 FROM VIEW ORDER BY C1)
BEGIN
EXEC msdb.dbo.sp_start_job
@job_name = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx'

END
--

IF EXISTS (SELECT C1 FROM VIEW)
BEGIN
EXEC msdb.dbo.sp_start_job
@job_name = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx'

END

SP2:

DECLARE @ExecRowCount INT

CREATE TABLE #Temp
(
    C1 CHAR(50), 
    C2 DECIMAL(10,0),
    C3 CHAR(50),
    C4 VARCHAR(4)
)

INSERT INTO #Temp
SELECT * FROM VIEW
SELECT @ExecRowCount = COUNT(*) FROM #Temp

DROP TABLE #Temp

IF(@ExecRowCount > 0)
BEGIN
EXEC msdb.dbo.sp_start_job
@job_name='xxxxxxxxxxxxxxxxxxxxxxxxxxxx'
END

SP3:

IF ((SELECT COUNT(*) FROM VIEW) > 0)
BEGIN
EXEC msdb.dbo.sp_start_job
@job_name = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx'

END

编辑2013/08/20: 我添加了我在SP1和SP3 @ C​​lick-Rex建议的其他条款。

抱歉,我忘了提到视图是在SQL 2000上。这是我将此视图的相关数据库恢复到SQL 2008 QAS后尝试的问题的根本原因。恢复后我没有更改任何设置。

结果是: SP1和SP3的时间不到1秒,SP2的时间不到20秒。

实际上,这种观点非常复杂。我在SQL 2000上尝试了其他简单的视图。“IF EXISTS”并没有花费太多时间。

感谢大家的反馈。 : - )

3 个答案:

答案 0 :(得分:1)

也许top 1部分使SQL Server选择了一个特别不幸的查询计划?尝试:

IF EXISTS (SELECT * FROM VIEW)

如果您发布两种变体的实际查询计划的屏幕截图,也会有所帮助。

答案 1 :(得分:0)

尝试这样的事情:

IF EXISTS (SELECT TOP 1 * FROM VIEW ORDER BY 1)

已知TOP N查询存在问题。这里有一些文章供你研究

http://use-the-index-luke.com/sql/partial-results/top-n-queries

http://sqlity.net/en/908/top-n-sort-a-little-bit-of-sorting/

Why select Top clause could lead to long time cost

答案 2 :(得分:0)

您也可以替换

IF EXISTS

使用与NULL

进行比较的查询

所以你也应该尝试切换像

这样的语句
IF EXISTS (SELECT TOP 1 * FROM VIEW)

IF (SELECT TOP 1 * FROM VIEW) IS NOT NULL

我记得曾经偶尔帮助过我