确定记录是否存在的最快方法

Sna*_*Doc 125 sql sql-server performance select count

正如标题所暗示的那样......我正在试图以最少的开销来找出最快的方法来确定表中是否存在记录.

示例查询:

SELECT COUNT(*) FROM products WHERE products.id = ?;

    vs

SELECT COUNT(products.id) FROM products WHERE products.id = ?;

    vs

SELECT products.id FROM products WHERE products.id = ?;
Run Code Online (Sandbox Code Playgroud)

假设?'TB100'... 交换...第一个和第二个查询将返回完全相同的结果(例如... 1对于此对话).最后一个查询将按'TB100'预期返回,如果id表中没有,则不返回任何内容.

目的是弄清楚id表中是否有.如果没有,程序将接下来插入记录,如果是,程序将跳过它或基于该问题范围之外的其他程序逻辑执行UPDATE查询.

哪个更快,开销更少?(每个程序运行将重复数万次,并且每天将运行多次).

(通过M $提供的JDBC驱动程序从Java运行此M $ SQL Server查询)

Nen*_*vic 172

EXISTS(或NOT EXISTS)是专门用于检查是否存在某些东西,因此应该(并且是)最佳选择.它将在匹配的第一行停止,因此它不需要TOP子句,它实际上不会选择任何数据,因此列的大小没有开销.你可以安全地SELECT *在这里使用- 没有什么不同SELECT 1,SELECT NULL或者SELECT AnyColumn...... (你甚至可以使用无效的表达式SELECT 1/0,它不会破坏).

IF EXISTS (SELECT * FROM Products WHERE id = ?)
BEGIN
--do what you need if exists
END
ELSE
BEGIN
--do what needs to be done if not
END
Run Code Online (Sandbox Code Playgroud)

  • @SnakeDoc No.`Exists`以`select`的方式工作,一旦找到一行就会退出.此外,仅存在记录,而不是记录中的实际值,从而节省了从磁盘加载行的需要(当然,假设搜索条件已编入索引).至于"如果"的开销 - 无论如何你将不得不花费这个微不足道的时间. (7认同)
  • @SnakeDoc要查找表结构,包括外键和索引,请运行[sp_help](http://technet.microsoft.com/en-us/library/ms187335.aspx)*table_name*.当从多个行中检索几行时,索引是必不可少的,进一步使用`select top`或`exists`; 如果它们不存在,sql引擎将不得不执行表扫描.这是最不理想的表搜索选项.如果您无权创建索引,则必须与另一方的技术人员进行通信,以确定他们是自动调整还是希望您建议索引. (3认同)
  • @Konstantin 你可以做类似`SELECT CASE WHEN EXISTS(..) THEN 1 ELSE 0 END;` (2认同)

Dec*_*n_K 153

SELECT TOP 1 products.id FROM products WHERE products.id = ?; 将超越您的所有建议,因为它会在找到第一条记录后终止执行.

  • 在通过PK(或任何其他唯一密钥)进行搜索时,优化程序是否会将其考虑在内? (5认同)
  • 如果它不是PK,我还建议确保该列上有索引.否则,查询将不得不进行表扫描而不是更快的表搜索. (4认同)
  • 他没有说过是PK,但如果是,那么优化器会考虑到这一点. (3认同)
  • @Declan_K:在这种情况下,我的魔法球似乎失败了,标题为"id"的列不是PK.所以给你的建议+1. (3认同)
  • 我想我们应该考虑@ nenad-zivkovic对这个问题的回答. (3认同)

Age*_*SQL 21

什么都不能打败 -

SELECT TOP 1 1 FROM products WHERE id = 'some value';
Run Code Online (Sandbox Code Playgroud)

您无需计算表中是否有数据.并且在不需要时不要使用别名.

  • 尽管名称`id`不是主键.所以,即使你没有*计算*,你仍然需要找到所有匹配的记录,可能还有数千个记录.关于别名 - 代码是不断进行的工作.你永远不知道什么时候你必须回去.别名有助于防止愚蠢的运行时错误; 例如,不需要别名*的唯一列名*不再是唯一的,因为有人在另一个连接表中创建了一个具有相同名称的列. (5认同)
  • 我不知道为什么我接受了"别名"一词.正确的术语是"合格".这是[Alex Kuznetzov的更长解释](http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/10/25/defensive-database-programming-qualifying-column-names.aspx).关于单个表查询 - 它是单个表*现在*.但是后来,当发现bug并且你正试图控制洪水时,客户很紧张,你加入另一张桌子只是为了面对错误信息 - 容易纠正的信息,但不是在这个出汗的时刻,一个小小的击球 - 并且你纠正了错误记住永远不会离开列... (3认同)

Kri*_*man 10

SELECT CASE WHEN EXISTS (SELECT TOP 1 *
                         FROM dbo.[YourTable] 
                         WHERE [YourColumn] = [YourValue]) 
            THEN CAST (1 AS BIT) 
            ELSE CAST (0 AS BIT) END
Run Code Online (Sandbox Code Playgroud)

这种方法为您返回一个布尔值.


ati*_*ker 8

你也可以使用

 If EXISTS (SELECT 1 FROM dbo.T1 WHERE T1.Name='Scot')
    BEGIN
         --<Do something>
    END 

ELSE    
     BEGIN
       --<Do something>
     END
Run Code Online (Sandbox Code Playgroud)


man*_*sad 6

下面是确定数据库中是否存在记录的最简单、最快的方法,好处是它适用于所有关系数据库

SELECT distinct 1 products.id FROM products WHERE products.id = ?;
Run Code Online (Sandbox Code Playgroud)


Ste*_*nar 6

不要以为还没有人提到它,但是如果您确定数据在您下面不会发生变化,您可能还希望应用NoLock提示以确保读取时不会被阻塞。

SELECT CASE WHEN EXISTS (SELECT 1 
                     FROM dbo.[YourTable] WITH (NOLOCK)
                     WHERE [YourColumn] = [YourValue]) 
        THEN CAST (1 AS BIT) 
        ELSE CAST (0 AS BIT) END
Run Code Online (Sandbox Code Playgroud)