优化 sql 计数查询

Posted

技术标签:

【中文标题】优化 sql 计数查询【英文标题】:Optomizing a sql Count Query 【发布时间】:2010-07-15 15:23:29 【问题描述】:

我对 SQL 还很陌生,所以我想知道我是否以最优化的方式执行此操作。

 SELECT DISTINCT ACCOUNTID, ACCOUNT_NAME
  (SELECT        COUNT(*)
  FROM            TICKET
  WHERE        (ACCOUNTID = OPPORTUNITY.ACCOUNTID)) AS [Number Of Tickets],
  (SELECT        COUNT(*)
  FROM            TICKET
  WHERE        (ACCOUNTID = OPPORTUNITY.ACCOUNTID) AND (STATUSCODE = 1 OR
         STATUSCODE = 2 OR
         STATUSCODE = 3)) AS [Active Tickets]
 from OPPORTUNITY
    where AccountID > @LowerBound and AccountID < @UpperBound

我想要做的是获取所有帐户的列表,并让它显示该帐户有多少票以及有多少是活动的(状态代码为 1、2 或 3)。选择中的选择是执行此操作的正确方法,还是可以使用 group by 之类的方法来完成。

我最担心的是速度,仅提取大约 20 条记录需要 3-5 秒,并且查询可能有 1000 条结果。

我不是 DBA,因此对表架构的任何更改都不是强制性的,但需要向高层管理人员提出一些请求。

这是针对 SQL Server 2000 运行的。

编辑—— 作为询问它的所有答案,我检查了它。 accountid 升序时的 Opportunity 和票证索引。

【问题讨论】:

是的,尤其是在处理制表符时,格式有时会有些棘手和“随机” :-) 很高兴知道您了解正确的格式 - 对可读性有很大影响! 【参考方案1】:

我认为下面的内容在逻辑上应该是等效的并且更有效。显然测试这两个方面你的目的!

 SELECT O.ACCOUNTID, O.ACCOUNT_NAME,
   COUNT(*) AS [Number Of Tickets],
   ISNULL(SUM(CASE WHEN STATUSCODE IN (1,2,3) THEN 1 ELSE 0 END),0) 
                                                                AS [Active Tickets]
 FROM OPPORTUNITY O
 LEFT OUTER JOIN TICKET T ON T.ACCOUNTID = O.ACCOUNTID
    WHERE O.ACCOUNTID > @LowerBound and O.ACCOUNTID < @UpperBound
    GROUP BY O.ACCOUNTID, O.ACCOUNT_NAME

如果您可以查看执行计划,那么您应该检查两个表中 ACCOUNTID 上是否存在索引并且正在使用。

【讨论】:

索引确实存在,我在执行计划上找什么看是否在使用? @Scott - 主要要看的是昂贵的运营商实际上是什么。您已经更新了您的问题,说您有索引,但只需 3-5 秒即可提取大约 20 条记录,这听起来比在这种情况下预期的要多。你试过我的查询吗?【参考方案2】:

SQL 引擎(即使在 2000 年)已经足够聪明,可以优化该 sql。根据你的性能数据和这么少的结果,我猜源数据有一堆记录并且没有 sql 需要的索引。

确保 Opportunity.AccountID 上有一个索引,Ticket.AccountID 上有一个索引。

【讨论】:

我同意你的索引。不太相信 SQL2000 会像你说的那样优化它。

以上是关于优化 sql 计数查询的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server SQL性能优化之--pivot行列转换减少扫描计数优化查询语句

如何优化执行嵌套在 group-by 子句中的计数的 SQL 查询?

用于计数和显示(列中的不同值)的 Sql 查询优化,按其他两列分组

SQL Server:计数请求优化

优化 Mysql 查询

从 EF 为 PostGresql 生成的查询中的非最佳计数