我有一个带MyField字段的表MyTable,它是varbinary(max)。我有以下查询:
SELECT COUNT(*) FROM MyTable WHERE MyField IS NOT NULL
SELECT子句可以有任何东西,没关系。由于Where子句中的varbinary MyField,执行永远不会结束。
我甚至试过这个:
SELECT Size
FROM
(
SELECT ISNULL(DATALENGTH(MyField), 0) AS Size FROM MyTable
) AS A
WHERE A.Size > 0
内部查询工作正常,没有Where子句的整个查询工作正常,但是使用Where子句它会被卡住。有人可以向我解释一下吗?
感谢。
答案 0 :(得分:6)
不要认为或假设它不可能阻塞,只是因为不同的查询立即返回。使用不同的where子句,不同的计划,以及可能不同的锁定升级,您当然可能会遇到一个查询被阻止而另一个查询被阻止的情况,即使对于同一个表也是如此。
如果您认为“卡住”的定义是我认为的那样,那么查询显然会被阻止。现在你只需要由谁决定。
在一个查询窗口中 ,请执行以下操作:
SELECT @@SPID;
记下这个号码。现在 在同一查询窗口中 ,运行“卡住”的查询(换句话说,不要在一个窗口中选择spid并期望它有任何内容处理已在另一个窗口中运行的查询)。
然后, 在另一个查询窗口中 ,执行以下操作:
SELECT blocking_session_id, status, command, wait_type, last_wait_type
FROM sys.dm_exec_requests
WHERE session_id = <spid from above>;
这是一个我怀疑可能有帮助的可视化(请注意我的“卡住”查询与您的不同):
如果您在第一列中获得非零数字,然后在该不同的查询窗口中 ,请执行以下操作:
DBCC INPUTBUFFER(<that blocking session id>);
如果你没有被阻止,我很想知道其他专栏的内容。
顺便说一句,更改WHERE
子句以使用稍微不同的谓词来标识相同的行并不会神奇地消除阻塞。此外,这样做没有任何实际好处:
SELECT Size
FROM
(
SELECT ISNULL(DATALENGTH(MyField), 0) AS Size FROM MyTable
) AS A
WHERE A.Size > 0
当你可以这样做时:
SELECT ISNULL(DATALENGTH(MyField), 0) AS Size
FROM dbo.MyTable -- always use schema prefix
WHERE DATALENGTH(MyField) > 0; -- always use semi-colon
如果您担心的话,SQL Server足够智能,无法计算DATALENGTH
两次。
答案 1 :(得分:5)
只是为了好玩和咯咯笑,我决定把这个扔给你。我在这里把一些事情视为理所当然,但你可以看看必须等待的任务。查找以LCK_
开头的等待类型,因为这些将是您的阻止任务。请注意,在繁忙的服务器上,环形缓冲区可能会在一段时间后翻转。另请注意,这是为了补充@ AaronBertran的优秀答案,绝不意味着取代它。他的内容更全面,是发现问题的正确方法。
SELECT
td.r.value('@name','sysname') event_name,
td.r.value('@timestamp','datetime2(0)') event_timestamp,
td.r.value('(data[@name="wait_type"]/text)[1]','sysname') wait_type,
td.r.value('(data[@name="duration"]/value)[1]','bigint') wait_duration,
td.r.value('(action[@name="sql_text"]/value)[1]','nvarchar(max)') sql_text,
td.r.query('.') event_data
FROM (
SELECT
CAST(target_data AS XML) target_data
FROM sys.dm_xe_sessions s
JOIN sys.dm_xe_session_targets t
ON s.address = t.event_session_address
WHERE s.name = N'system_health'
and target_name = 'ring_buffer'
) base
CROSS APPLY target_data.nodes('/RingBufferTarget/*') td(r)
where td.r.value('@name','sysname') = 'wait_info';