带有varbinary的where子句不起作用

时间:2014-01-21 18:44:50

标签: sql-server sql-server-2008

我有一个带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子句它会被卡住。有人可以向我解释一下吗?

感谢。

2 个答案:

答案 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>;

这是一个我怀疑可能有帮助的可视化(请注意我的“卡住”查询与您的不同):

  

click to embiggen

如果您在第一列中获得非零数字,然后在该不同的查询窗口中 ,请执行以下操作:

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';