问题:将一个相对较小的表连接到具有多个连接的查询中会使查询的执行时间加倍。
挑战:如何优化查询或数据结构,以便查询执行得更快?
到处都有索引,统计数据是实际的。
3次传递,使用SQL Server Profiler测量:
基本上,查询是关于从大型预算表中过滤和聚合值。
budget
包含大约700,000条记录f1
,f2
,f3
,其中包含用户选择的值。这些过滤表有1到最大。 70条记录对于汇总,我们有表a1
,a2
,a3
,用于将维度聚合到组聚合。
预算表:700,000条记录
原始查询:
select a1.agg1, a2.agg2, a3.agg3, sum(b.value)
from
budget b -- 700.000 records
inner join f1 on b.dim1 = f1.dim1
inner join f2 on b.dim2 = f2.dim2
inner join f3 on b.dim3 = f3.dim3
inner join a1 on b.dim1 = a1.dim1
inner join a2 on b.dim2 = a2.dim2
inner join a3 on b.dim3 = a3.dim3
group by a1.agg1, a2.agg2, a3.agg3
order by a1.agg1, a2.agg2, a3.agg3
现在我添加了左连接。它带来了额外的额外计数表,其中包含对某些数字的评论。
因此,此连接会在结果中添加一列,但不会更改行。
表comments
只有大约1,500条记录。
新查询:
select a1.agg1, a2.agg2, a3.agg3, sum(b.value), count(c.CommentText) as commentcount
from
budget b -- 700.000 records
inner join f1 on b.dim1 = f1.dim1
inner join f2 on b.dim2 = f2.dim2
inner join f3 on b.dim3 = f3.dim3
inner join a1 on b.dim1 = a1.dim1
inner join a2 on b.dim2 = a2.dim2
inner join a3 on b.dim3 = a3.dim3
left join comments c on b.dim1= c.dim1 and b.dim2=c.dim2 and b.dim3=c.dim3
group by a1.agg1, a2.agg2, a3.agg3
order by a1.agg1, a2.agg2, a3.agg3
我详细比较了两个查询的执行计划。额外的左连接导致3次额外操作,费用如下:
排序是一种额外的排序,仅与联接一起出现。使用额外的连接,我有两种排序(合并连接之前和之后),否则只有一种。
有趣的是,成本与现实并不完全匹配。但无论如何。基本问题是:如何改进?有任何想法吗?