持续扫描需要0秒或2-3分钟


9

像下面这样的查询(保证不会返回任何行)在我们的其中一台服务器上花费了0到160秒的时间:

select col1, col2, col3
from tab1
where 0 = 1

两周前,这种情况每隔48小时发生了六次。上周,同一查询花费了约0秒。我有应用程序SQL的日志,但尚未发现任何可疑对象。此外,我认为顶级0/0 = 1的类型查询从未命中数据页,因此它应该能够抵抗行/页/表级数据锁吗?任何(已知)SQL都不会涉及该架构。

由于问题不一致,并且服务器承受的负载非常重,因此我想在附加SQL事件探查器之前了解发生的情况的理论。在这些延迟期间,其他查询可以正常运行。应用程序中的一个已知问题是大量动态创建的SQL查询-在48小时内大约有200k唯一查询,总共850k(记录的)查询,这会引起这样的问题吗?

该服务器运行SQL Server 2005标准版,96 GB RAM,SAN上的磁盘和4个CPU / 16核。数据库文件和文件组已经过优化,应该没有问题(但是我们正在分别研究)。

任何在哪里看的指针都将不胜感激。

编辑:完美!重播查询以添加执行计划,这花了1分钟35秒。这是执行计划和显示查询持续时间的屏幕截图: 查询计划

编辑2:统计第二次运行的时间详细信息。现在似乎一直很慢,因此我们将附加探查器和perfmon:

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 97402 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

您能附上执行计划吗?执行前在查询窗口中按CTRL + M。
Craig Efrein 2014年

2
可能是锁定问题吗?来自其他会话的DML语句阻止了对表的选择(这是SQL Server 2005中的默认行为)
a_horse_with_no_name 2014年

没有任何已知的DML语句,这是我能想到的唯一原因,但我们仍在对此进行调查。执行计划已添加到问题中。
EventHorizo​​n 2014年

根据我的阅读,这只是MSSQL在优化程序知道没有要返回的行时避免读取堆和索引的那些琐碎的执行计划之一
Craig Efrein 2014年

1
看到了一个看起来像这样的箱子。原来是触发更新统计信息(打开了自动更新统计信息,并且维护计划已损坏)。
约书亚2014年

Answers:


18

似乎即使有一个... WHERE 0 = 1子句,仍然需要IS在表上使用意图共享()锁。让我们证明一下:

我将从创建测试表开始:

use TestDb1;
go

create table dbo.MyTestTable1
(
    Id int identity(1, 1) not null,
    SomeInt int not null
);
go

insert into dbo.MyTestTable1 (SomeInt)
values (10), (20), (30), (40), (50);
go

现在我有了测试表,在一个会话(查询窗口)中,我将执行以下操作以对独占(X)锁定dbo.MyTestTable1

use TestDb1;
go

begin tran;
    select
        Id, SomeInt
    from dbo.MyTestTable1 with (tablockx);
--commit tran;

我可以通过查看sys.dm_tran_locksDMV 来验证排他锁。然后在另一个会话(新查询窗口)中,我完全执行您的查询:

use TestDb1;
go

select
    Id, SomeInt
from dbo.MyTestTable1
where 0 = 1;

乍一看,我发现它还没有完成。看一下sys.dm_exec_requests,我确切地知道为什么会这样:

select
    r.session_id,
    r.status,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    r.blocking_session_id
from sys.dm_exec_requests r
cross apply sys.dm_exec_sql_text(r.sql_handle) st
where st.text like '%where 0 = 1%'
and r.session_id <> @@spid;

在此处输入图片说明

我在这里看到我的... WHERE 0 = 1查询正在等待IS对此对象的锁定(object_id转换为dbo.MyTestTable1)。

我绝不是说并发是您的问题,但是从声音的角度看,您正在表现出症状。上面的示例旨在证明即使使用WHERE永远不会返回数据的子句,您也不会免于锁定和阻塞。

我们所能做的只是猜测,因此当它“花很长时间”时,您需要做的就是确切地了解该请求正在执行的工作,这花费了很长时间。如果它在等待某些东西,那么看看它在等待什么。


1

根据查询的尖峰和线程需求,系统可能只是在对该查询进行排队。安装程序的默认工作程序计数(即,同时运行的SQL Server线程数)应为700。

检查sys.dm_os_schedulers和sys.dm_os_waiting_tasks来查看是否可能是一个问题。


一个很好的建议,但问题最终归结为愚蠢的锁。
EventHorizo​​n 2014年

我并没有真正相信,因为有700名工人,但检查起来很容易(因此可以排除)
Sascha Rambeaud 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.