【问题标题】:SQL SUM or COUNT with CASE - which would be more efficientSQL SUM 或 COUNT 与 CASE - 这会更有效
【发布时间】:2014-04-25 04:23:37
【问题描述】:

如果我有一个主键为 subject_id (INT) 和 category_id (INT) 的 SQL Server 2008 R2 数据库表和一个位掩码列(是的,恐怖位掩码!,但它就是这样,位掩码不会吓到我,以及为清楚起见已省略的其他列)...

鉴于以下两个查询,哪个更有效?我尝试使用客户端统计信息和执行计划输出,但每次运行查询时统计信息似乎都不同,并且本身并没有明确的赢家。

查询 1:

SELECT SUM( CASE WHEN ( category_id = 1 AND ( bit_mask & 4 ) = 4 ) THEN 1
                 WHEN ( category_id = 2 AND ( bit_mask & 8 ) = 8 ) THEN 1
                 ELSE 0 END )
FROM data_tbl
WHERE subject_id = 12;

查询 2:

SELECT COUNT(*)
  FROM data_tbl
 WHERE subject_id = 12
   AND 1 = ( CASE WHEN ( category_id = 1 AND ( bit_mask & 4 ) = 4 ) THEN 1
                  WHEN ( category_id = 2 AND ( bit_mask & 8 ) = 8 ) THEN 1
                  ELSE 0 END );

如果某些 SQL 专家可以查看并立即判断哪个查询更有效(或者它们是否相同?),请告诉我。

提前致谢!

【问题讨论】:

  • 您为什么不自己在 Mgmt Studio 中运行这两个查询并进行比较!您可以使用实际的执行计划和执行统计信息来查看两者的性能对比......
  • 我做到了,但正如我在原帖中提到的,统计数据似乎每次都不同(没有明确的赢家);可能是我在运行测试之前做错了什么。

标签: sql-server sql-server-2008-r2 count sum case


【解决方案1】:

两者都不是。这应该优于两者:

SELECT COUNT(*)
FROM data_tbl
WHERE subject_id = 12
AND (
  (category_id = 1 AND ( bit_mask & 4 ) = 4 ) 
  OR 
  (category_id = 2 AND ( bit_mask & 8 ) = 8 )
)

原因是这个查询使优化器有更好的机会使用索引或其他方式处理逻辑。您的查询将计数逻辑隐藏在优化器无法处理的计算中。

【讨论】:

    【解决方案2】:

    像往常一样,它主要取决于基数和选择性。我的猜测是第二个有更好的机会更快。对照您的真实数据检查执行计划以确保确定。

    然而,最快的变种可能是这个:

    SELECT SUM( CASE WHEN ( category_id = 1 AND ( bit_mask & 4 ) = 4 ) THEN 1
                     WHEN ( category_id = 2 AND ( bit_mask & 8 ) = 8 ) THEN 1
                     ELSE 0 END )
    FROM data_tbl
    WHERE subject_id = 12
    AND category_id in (1, 2);
    

    同样,这只是一个猜测,它可能很容易被 UNION ALL(每个 category_id 一个 SELECT)所超越。

    【讨论】:

      【解决方案3】:

      好的 - 感谢大家的回复 - 我测试了提供的建议,以下是查询分析器报告的结果:

      查询 1:

      SELECT SUM( CASE WHEN ( category_id = 1 AND ( bit_mask & 4 ) = 4 ) THEN 1
                       WHEN ( category_id = 2 AND ( bit_mask & 8 ) = 8 ) THEN 1
                       ELSE 0 END )
       FROM data_tbl
      WHERE subject_id = 12
        AND category_id in ( 1, 2);
      

      10 次试验后的平均“总执行时间”:10.8

      查询 2:

      SELECT COUNT(*)
       FROM data_tbl
      WHERE subject_id = 12
        AND ( ( category_id = 1 AND ( bit_mask & 4 ) = 4 ) OR 
              ( category_id = 2 AND ( bit_mask & 8 ) = 8 ) );
      

      10 次试验后的平均“总执行时间”:11.6

      奇怪的是,两种情况下的执行计划看起来都是一样的。所以它看起来像查询 1 将成为要使用的查询。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-05
        • 1970-01-01
        • 2013-02-06
        • 2014-02-24
        • 2012-06-30
        • 2012-12-02
        相关资源
        最近更新 更多