SQL优化,列列表上的条件会影响优化吗?

Posted

技术标签:

【中文标题】SQL优化,列列表上的条件会影响优化吗?【英文标题】:SQL Optimization, Does conditions on column list affect optimization? 【发布时间】:2018-03-26 08:50:35 【问题描述】:

我觉得标题不够清楚(请指教)

假设我有这个假设的查询

  SELECT
    Name,
    P.Amount,
    count(DISTINCT PI.Id)
  FROM Customer C
    LEFT JOIN Purchase P ON C.Id = P.CustomerId
    LEFT JOIN Flags F ON P.Id = F.PurchaseId AND F.Name = 'showItems'
    LEFT JOIN PurchseItems PI ON PI.PurchseId = P.Id AND F.Value = 'TRUE'
  WHERE C.Id = @customerId
  GROUP BY Name, P.Amount, F.Value

或者

SELECT
  Name,
  P.Amount,
  CASE WHEN F.Value = 'TRUE' THEN count(DISTINCT PI.Id) ELSE 0 END As ItemsCount
FROM Customer C
  LEFT JOIN Purchase P ON C.Id = P.CustomerId
  LEFT JOIN Flags F ON P.Id = F.PurchaseId AND F.Name = 'showItems'
  LEFT JOIN PurchseItems PI ON PI.PurchseId = P.Id
WHERE C.Id = @customerId
GROUP BY Name, P.Amount, F.Value

无论如何,其中一个会帮助查询优化器吗?我正在使用 MS SQL 服务器。我想知道列列表上的条件是否有影响?


我的猜测是,如果F.Value 不是'True',则查询根本不必通过加入PurchaseItems


编辑:在 Group by 中添加了 F.Value,因为它在每次购买时都是唯一的

我没有将其移近计数以保持查询或多或少相同。这个问题的想法是比较连接和选择列表的条件。

【问题讨论】:

当然您可以自己检查差异,只需运行两个查询。假设有一个 GROUP BY 你的第二个查询根本不会运行,它应该是COUNT( DISTINCT CASE WHEN F.Value = 'TRUE' THEN PI.Id END As ItemsCount。否则无论如何都必须检查条件,最昂贵的操作将是 DISTINCT。 @dnoeth 您忘记在 SQL 中关闭括号。 :) 您不能拥有没有分组依据的聚合。编写有效的查询并比较执行计划。 语法仍然无效。 当您将 CASE 移动到 COUNT 中时,您将获得 working 查询,目前您只会收到一条错误消息:Msg 8120 Level 16 State 1 Line 1 列“F.Value”在选择列表中无效,因为它不包含在聚合函数或 GROUP BY 子句中。 【参考方案1】:

如果有一些记录 F.Value 'TRUE'

,您的第一个查询比第二个查询要好

第一次查询将过滤记录到点或更少的记录。所以查询会很快。

实际行数会更少。

第二次查询将获取更多结果集,然后再次应用 case 语句来获取正确的 ItemCount。

实际行数会更多。

不对您的其余查询或要求发表评论。

【讨论】:

【参考方案2】:

一般来说: SELECTION(ON 子句和 WHERE 子句)越具体,您为优化器提供优化的句柄就越多。 在此基础上,您的第一个查询应该是最好的查询。

运行两个查询:

-- dbcc dropcleanbuffers -- 清理数据缓存。

-- dbcc freeproccache -- 清理编码缓存。

开启统计时间

设置统计 IO 开启

获得有关查询费用的印象。

【讨论】:

以上是关于SQL优化,列列表上的条件会影响优化吗?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle SQL - FROM 子句中的 JOIN 顺序会影响性能优化吗?

数据库数据库优化(SQL优化)

【DB2】SQL优化

SQL语句的几种优化方法

SQL性能优化

如何对Oracle sql 进行性能优化的调整