【问题标题】:Optimizing a T-SQL query with COUNT in the SELECT and HAVING statements在 SELECT 和 HAVING 语句中使用 COUNT 优化 T-SQL 查询
【发布时间】:2016-02-06 15:15:08
【问题描述】:

我不确定这是否与我正在处理非常大的表(有些表有 900+ 百万行)有关,但我在优化查询时遇到了问题。我还尽可能检查并使用了索引字段,我的查询中使用的大多数字段实际上都被索引了。使用select top 100 语句大约需要 10 分钟,我希望更快地获取所有结果.我将如何优化此查询和未来的类似查询?为了安全起见,我不得不使用下面的替代别名:

SELECT TOP 100 
    x.ID, j.ID, j.FirstDate, j.ExpiryDate, x.Lock, COUNT (*) as Numbers
FROM
   j WITH(NOLOCK)
INNER JOIN   
   jp WITH(NOLOCK) ON j.ID = jp.ID
INNER JOIN   
   jd WITH(NOLOCK) ON (jd.ID = jp.ID And jd.path = 3)
INNER JOIN  
   fa WITH(NOLOCK) ON fa.ID = j.ID
INNER JOIN  
   l WITH(NOLOCK) ON j.ID = l.ID AND l.CoID = 3
INNER JOIN   
   c WITH(NOLOCK) ON c.CID = fa.CID
INNER JOIN  
   x WITH(NOLOCK) ON c.CID = x.CID
WHERE  
   j.ExpiryDate > GETDATE()
GROUP BY 
   x.ID, j.ID, j.FirstDate, j.ExpiryDate, x.Lock
HAVING 
   COUNT(*) <= 10

【问题讨论】:

  • 设置Bad Habits to kick - putting NOLOCK everywhere - 不推荐在任何地方使用它 - 恰恰相反!
  • 按那个按钮查看解释计划并附在此处
  • 如果不是getdate(),我会说物化视图值得一看。
  • 删除 WITH(NOLOCK) 没有任何区别,但链接读起来很有趣。

标签: sql sql-server tsql join optimization


【解决方案1】:

试试这个

SELECT TOP 100 
    x.ID, j.ID, j.FirstDate, j.ExpiryDate, x.Lock, COUNT (*) as Numbers
FROM
   j WITH(NOLOCK)
INNER JOIN   
   jp WITH(NOLOCK) ON j.ID = jp.ID 
                  and j.ExpiryDate > GETDATE()
INNER JOIN   
   jd WITH(NOLOCK) ON (jd.ID = jp.ID And jd.path = 3)
INNER JOIN  
   fa WITH(NOLOCK) ON fa.ID = j.ID
INNER JOIN  
   l WITH(NOLOCK) ON j.ID = l.ID AND l.CoID = 3
INNER JOIN   
   c WITH(NOLOCK) ON c.CID = fa.CID
INNER JOIN  
   x WITH(NOLOCK) ON c.CID = x.CID      
GROUP BY 
   x.ID, j.ID, j.FirstDate, j.ExpiryDate, x.Lock
HAVING 
   COUNT(*) <= 10

【讨论】:

  • 我看到很多这样的行为,我不明白为什么人们会跳到一个问题上,只是对其他人投反对票。
【解决方案2】:

有时它有助于减少派生表中的数据集,然后仅对满足 where 条件的数据应用该函数。没有看到两者的执行计划,我不知道这是否可行,但值得一试。

SELECT  a.XID, a.JID, a.FirstDate, a.ExpiryDate, a.Lock, COUNT (*) as Numbers
FROM (
SELECT 
    x.ID as XID, j.ID as JID, j.FirstDate, j.ExpiryDate, x.Lock
FROM
   j 
INNER JOIN   
   jp  ON j.ID = jp.ID
INNER JOIN   
   jd  ON (jd.ID = jp.ID And jd.path = 3)
INNER JOIN  
   fa  ON fa.ID = j.ID
INNER JOIN  
   l ON j.ID = l.ID AND l.CoID = 3
INNER JOIN   
   c  ON c.CID = fa.CID
INNER JOIN  
   x ON c.CID = x.CID
WHERE  
   j.ExpiryDate > GETDATE()) a
GROUP BY 
  a.XID, a.JID, a.FirstDate, a.ExpiryDate, a.Lock
HAVING 
   COUNT(*) <= 10

【讨论】:

    猜你喜欢
    • 2023-02-03
    • 1970-01-01
    • 1970-01-01
    • 2015-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-25
    • 1970-01-01
    相关资源
    最近更新 更多