【发布时间】: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