【问题标题】:Sql server query optimizer seems to do something wrong [closed]Sql server 查询优化器似乎做错了什么[关闭]
【发布时间】:2014-04-19 20:07:02
【问题描述】:
SELECT
    My.id,
    SUM (CountResults.Quantity) as TotalQuantity
FROM 
    (SELECT
        My.*, 
        ROW_NUMBER() OVER (ORDER BY My.Date DESC) AS RowNumber
     FROM [Test] My) My
OUTER APPLY
    (SELECT *
     FROM  ( /* really expensive query */ ) CR
     WHERE My.RowNumber = 1   
        /* I expect that optimizer will execute query only once for 1st row */
    ) CountResults
GROUP BY  
    My.id

我真正看到的是,查询的执行时间比我预期的要长得多(我测量了一次内部查询执行的时间,大约是 0.1 秒,我的查询执行时间要长得多)

我错过了什么吗?

PS:计划以.sqlplan格式https://www.dropbox.com/s/vn6oy69z5xbuuug/Plan%201.sqlplan 使用WHERE [My].[RowNumber] = 1 与不使用的查询。 如您所见,上面写着 50% 到 50%,这很奇怪。

我也试过了:

LEFT JOIN
(   
   SELECT *  FROM  ( /* expensive query */ ) as [1]
) as CountResults ON My.RowNumber = 1

什么都没有改变。

【问题讨论】:

  • 旁注:如果您有多个表和嵌套的子查询 - 我会建议 NOT 为它们都赋予相同的表别名!
  • 执行计划怎么说?毫无意义的推测,而不是获取不同查询产生的实际计划并进行比较。
  • 我在主题中添加了执行计划的链接:dropbox.com/s/vn6oy69z5xbuuug/Plan%201.sqlplan
  • [My] [eyes] [bleed] [from] [these] [ugly] [brackets] [.]
  • 外部应用查询内部是否存在相关性?似乎不是,因此可以将其重写为简单的CROSS JOIN 而不是GROUP BY

标签: sql sql-server optimization


【解决方案1】:

如果外部应用子查询不相关 - 似乎不相关 - 那么您不必使用 OUTER APPLY。您可以使用简单的LEFT JOIN 重写而不使用GROUP BY,将聚合移动到不相关的子查询中:

SELECT
    My.id,
    CountResults.TotalQuantity
FROM 
    (SELECT
        My.id, 
        ROW_NUMBER() OVER (ORDER BY My.Date DESC) AS RowNumber
     FROM [Test] My
    ) My
  LEFT JOIN
    (SELECT SUM(Quantity) AS TotalQuantity
     FROM  ( /* really expensive query */ ) CR
    ) CountResults
    ON  My.RowNumber = 1 ;  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-19
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    相关资源
    最近更新 更多