【问题标题】:SQL: Ignore irrelevant JOIN when aggregating over the core tableSQL:聚合核心表时忽略不相关的 JOIN
【发布时间】:2020-12-16 07:24:03
【问题描述】:

假设我有表格:

dbo.Purchases
Id | Value | UserId
1 | 10.00 | 3
2 | 1.00 | 1
3 | 15.50 | 2
4 | 13.40 | 1

dbo.Users
Id (UQ) | Name
1 | Bob
2 | Sarah
3 | Alex

还有一个视图:

dbo.PurchasesWithUsers

SELECT *
  FROM dbo.Purchases
  LEFT JOIN dbo.Users ON Users.Id = UserId

我要运行SELECT SUM(Value) FROM dbo.PurchasesWithUsers

现在...作为人类,我可以看到 JOIN 不会影响该查询:

  • SUM中显然没有直接使用。
  • 这是一个LEFT JOIN,所以它不能排除Purchase行。
  • 它连接到具有UQ 约束的列,因此它不能重复 Purchase 行。

但是当我运行查询并查看执行计划时,引擎(MS SQL Server)仍在执行 JOIN,这会降低性能:(。

我有什么方法可以给引擎额外的线索,让它可以完全跳过 JOIN,同时仍然使用 VIEW 作为我查询的东西? p>


上下文:

  • 显然,这些表格非常庞大,这就是性能影响如此重大的原因
  • 表和视图显然比这复杂一点,但实际上并没有那么复杂 - 逻辑简化仍然有效,并且 UQ 约束是明确的(作为 UQ CONSTRAINT 或 UQ 索引)。
  • 正在使用 VIEW,以便用户可以过滤各种不同的选项。数据 API 处理这些选项并将相关的 WHERE 子句应用于单个 VIEW。唉,这意味着各种 JOIN 与 VIEW 无关,具体取决于选择的过滤器:(
  • 我知道我可以实现并直接索引 VIEW,但如果可能的话,我宁愿避免这种情况,因为我可以看到逻辑上已经存在更简单的查询计划。

【问题讨论】:

  • 解决方案是不要使用您的VIEW 来执行此操作。使用SELECT SUM([Value]) FROM dbo.Purchases;。另一个表 (Users) 确实需要考虑,好像存在一对多关系,[value] 的总和会有所不同。所以需要检查行。
  • "..逻辑简化仍然有效..." 我们愿意相信,但它通常不是一个正确的假设。发布所涉及对象的计划、查询和 DDL。没有必要的细节,只能猜测。优化器可以非常聪明并且“看穿”无用的连接。查询也很少会汇总表中的所有内容(无论分组如何)——尤其是巨大的表。这似乎比发布的要多得多。
  • @Larnu。不,它没有。因为它不能是一对多的,因为它定义了唯一性约束,如前所述。
  • “不,它没有。”你知道的,@Brondahl。 SQL Server 仍然需要检查这一点。因此,最简单的方法是执行 JOIN。

标签: sql-server performance sql-execution-plan


【解决方案1】:

除非建立索引,否则视图不会作为存储在数据库中的一组数据值存在。数据的行和列来自定义视图的查询中引用的表,并在引用视图时动态生成。因为您不想“直接索引 VIEW”,所以没有其他数据可以使用,并且服务器正在使用视图后面的查询获取数据,因此无法解决用这种方法避免LEFT JOIN

【讨论】:

  • 这主要是在谈论 VIEW 的本质。我完全意识到这一点 - 有趣的问题是,如果它不影响结果,您是否可以通过 JOIN 获得一个查询以忽略该 JOIN。
猜你喜欢
  • 2017-07-27
  • 1970-01-01
  • 2014-11-26
  • 1970-01-01
  • 2018-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多