“SELECT TOP 1 1”VS“IF EXISTS(SELECT 1”

时间:2012-06-13 06:00:29

标签: .net sql-server

我有一些.NET代码,可以在中等高的时间间隔内检查是否存在SQL记录。我希望尽可能让这张支票“便宜”。

我想知道两个查询的特征:

IF EXISTS(SELECT 1
          FROM   BigTable
          WHERE  SomeColumn = 200)
  SELECT 1 AS FOUND
ELSE
  SELECT 0 AS FOUND

VS

SELECT TOP 1 1
FROM   BigTable
WHERE  SomeColumn = 200 

他们都制定了类似的执行计划。但是SELECT TOP 1 1似乎执行得更快:解析查询次数越少,找不到记录时,它就会减少管道传输量。我也假设它在客户端运行得更快,因为我只需要检查记录计数,而不是编组IF EXISTS的返回值。

大多数性能优势可以忽略不计。但如果两者始终返回相同的结果,那么为什么不选择稍微更快的方法?

“SELECT TOP 1 1”是检查.NET中是否存在记录的最佳方法吗?

(我们使用.NET 3.5,我试图避免LINQ,因为它没有在应用程序的其他地方使用。我们还有一些我们正在迁移/重写的传统VB6应用程序,所以他们可能也需要执行它。)

编辑: 关于设计的更多细节。此记录是“标题”。还有另一个表具有子记录,当找到此标头时将对其进行读取/解析。缺乏记录是件好事:没有工作要做。

EDIT2:缺乏符合条件的记录将更频繁地发生。它们是零星的波浪。

5 个答案:

答案 0 :(得分:36)

我建议使用IF EXISTS(SELECT * ...),除非这实际上导致性能问题。它以比备选方式更好理解的方式表达查询的 intent

我会避免COUNT(*)(如当前答案中所述),除非您实际上需要表中的行数。

如果你想从结果中检查rowcount的“效率”,我可能会选择:

select 1 where exists(select * from BigTable where SomeColumn=200)

与第二个查询(0或1行)生成相同的结果集

答案 1 :(得分:11)

这是你想要的而不是IF语句

  SELECT ISNULL(
     (SELECT TOP 1 1 FROM BigTable where SomeCol = 200), 0);

答案 2 :(得分:1)

我肯定会选择第二个选项:

SELECT TOP 1 1
FROM   BigTable
WHERE  SomeColumn = 200 

即使I / O和CPU数量大致相同,执行计划也更简单有效。

答案 3 :(得分:1)

完全没有区别,存在甚至不会评估语句的选择部分。因此,请使用您喜欢的那个。

declare @test table (name varchar(20))

-- comment out inserts for testing.
insert into @test (name) values ('bob the builder')
insert into @test (name) values ('bob the builder')

-- for giggles, put 1/0 here. You'll find that divide by zero error.
select 1 from @test

-- notice that you don't receive a divide by zero error.
-- the bit in the select portion is never executed, ever.
if not exists (select 1/0 from @test) select 'Yay!'
if     exists (select 1/0 from @test) select 'Boo!'

实际上,您可以将它们互换使用:

... select * ... 
... select 1 ... 
... select top 1 * ... 
... select top 1 1 ... 
... select 'John Jacob Jingleheimer Schmidt' ... 

答案 4 :(得分:-13)

不确定SQL Server,但在其他数据库中,标准方法是:

SELECT COUNT(*) FROM BigTable where SomeCol = 200;

实际效率取决于您的索引等。