【问题标题】:Optimizing SELECT COUNT to EXISTS将 SELECT COUNT 优化为 EXISTS
【发布时间】:2011-02-17 16:09:05
【问题描述】:

我有一个查询要从表中查找某些客户。

SELECT COUNT(*)
  FROM CUSTOMER
 WHERE amount <> 0
   AND customerid = 22

customerid 上有一个索引,因此数据库会扫描 customerid = 22 的所有行。

由于结果是通过检查计数是否返回零或大于零来处理的,我该如何优化查询? IE。这样,在金额 0 的第一个客户行,查询返回 0,否则如果所有行都 = 0,则返回 1。

【问题讨论】:

标签: sql sql-server tsql


【解决方案1】:
select case
         when exists (select *
                      from   customer
                      where  amount <> 0
                             and customerid = 22) then 1
         else 0
       end  as non_zero_exists

【讨论】:

  • 用“select customerid”或“select 1”替换“select *”会更有效吗?
  • @CarloV.Dango 来自内存 SQL Server 2005 及更高版本已添加优化,使得存在和计数检查的速度与相同速度相同。
  • @BertusKruger 这仅适用于针对0 的COUNT 测试在查询中,而不是在原始问题中。我想知道TOP 1 是否会优化它。
【解决方案2】:

关于 customerid 和金额的第一个索引

CREATE INDEX customer_idx ON customer(customerid, amount); 

然后将您的查询重写为

IF EXISTS (SELECT customerid
    FROM customer
    WHERE amount > 0 -- I am assuming here that amount cannot be a negative number.
    AND customerid = 22)
   SELECT 1
ELSE
   SELECT 0

这将导致在 customer_idx 上进行索引查找。否则,您需要扫描该客户的所有行(您的问题似乎暗示可能很多)。

【讨论】:

  • +1 每个 SQL 性能问题的解决方案首先是创建适当的索引。
  • @Chris 这会产生“关键字附近存在不正确的语法”,尽管索引位很好
  • 对不起,在 SO 窗口中编码,总是一个错误的决定。更新为使用更像您的查询的内容。为您的回答 +1。
  • 是的,但是长时间运行的阻塞查询也可以在正确索引的数据上运行。
  • 不管怎样,它们不会导致死锁。但是,它们可能会加剧插入繁重的工作负载导致的死锁。
【解决方案3】:

看起来很直接

IF EXISTS ( SELECT customerid
            FROM   customer
            WHERE  amount <> 0
                  and customerid = 22))
   SELECT 1
ELSE
   SELECT 0

【讨论】:

    【解决方案4】:

    EXISTS 的替代品

    select ISNULL((select TOP 1 1
                   from customer
                   where amount <> 0
                     and customerid = 22),0)
    

    我已经假设您将有一个关于 (customerid) 或更好 (customerid,amount) 的索引。

    【讨论】:

      猜你喜欢
      • 2016-07-27
      • 1970-01-01
      • 2021-12-21
      • 2016-08-14
      • 1970-01-01
      • 2018-04-22
      • 1970-01-01
      • 1970-01-01
      • 2011-01-17
      相关资源
      最近更新 更多