我在两个我认为是等效的语句之间得到了不同的响应:SELECT COUNT(*)vs NOT EXISTS。在50个执行中,有约49个执行这两个语句的行为相同,但有时却不相同。
我的猜测是这些语句如何处理锁定的页面或其他更“遥不可及”的方法之间存在差异。我的问题是那有什么区别?
我最初在SPROC中添加了一些日志记录(语句3),这就是我看到它们具有不同值的方式。由于在TableWithResults执行此SPROC 时can 的内容可以更改,因此我添加了STATEMENT#3,以便可以确认COUNT(*)之前和之后的结果NOT EXISTS:
-- STATEMENT 1: If this is returning 1...
SET @MatchingResultCount1 = ( SELECT COUNT (*) FROM TableWithResults WHERE SearchId = @SearchId )
-- STATEMENT 2: ...I expect this to evaluate "False" and sets IS_VALID='Y'
IF NOT EXISTS ( SELECT * FROM TableWithResults WHERE SearchId = @SearchId )
SET @IS_VALID = 'N';
ELSE
SET @IS_VALID = 'Y';
-- STATEMENT 3: This is to confirm the table didn't change
SET @MatchingResultCount1 = ( SELECT COUNT (*) FROM TableWithResults WHERE SearchId = @SearchId )
Run Code Online (Sandbox Code Playgroud)
我所看到的是@MatchingResultCount1并且@MatchingResultCount2始终都是100%相同。几乎所有的时间@IS_VALID = 'Y'的时候@MatchingResultCount1 > 0,但1/50,@IS_VALID = 'N'时@MatchingResultCount1 > 0。
我尝试WITH (NOLOCK)在所有语句上使用,但这似乎没有什么不同。
通常你应该更喜欢NOT EXISTS在COUNT(*)一个非常简单的原因:
当您说时COUNT(*),数据库不知道您是否真的不在乎确切的行数。因此,一旦找到至少一个与该WHERE子句匹配的行,它就不能跳过其余结果。
现在,作为副作用,如果在设法跳过行的情况下,这也可能导致COUNT(*)查询获得比NOT EXISTS查询更多的锁NOT EXISTS。这将取决于数据库(我不确定SQL Server)