暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

预估执行计划和实际执行计划能有很大的不同?

原创 寒雨 2022-08-16
690

预估执行计划和实际执行计划能有很大的不同?

关于这个疑问,实时上就MSSQL而言,预估计划和实际执行计划经常会不同。

以下给出一个案例。

DropIndexes;

GO

CREATE INDEX Location ON dbo.Users(Location);

CREATE INDEX UserId ON dbo.Comments(UserId);

CREATE INDEX Score ON dbo.Comments(Score);

GO

然后通过存储过程模拟数据插入。

CREATE OR ALTER PROC dbo.TopCommentsByLocation

@Location NVARCHAR(100) AS

BEGIN

CREATE TABLE #UsersIWant (Id INT);

INSERT INTO #UsersIWant (Id)

SELECT Id

FROM dbo.Users

WHERE Location = @Location;

SELECT TOP 100 c.Score, u.DisplayName, c.CreationDate, c.Text

FROM #UsersIWant t

INNER JOIN dbo.Users u ON t.Id = u.Id

INNER JOIN dbo.Comments c ON t.Id = c.UserId

ORDER BY c.Score DESC;

END

GO

然后我们执行以下语句。

EXEC TopCommentsByLocation N'China';

预估的执行计划如下:

结合上图从右至左,从上至下,我们可以看到MSSQL使用单核执行,没有并发。

执行步骤如下:

  1. 扫描临时表。
  2. 针对Users对象上的聚合索引进行查找。
  3. 结合Userid索引扫描Comments表对象。
  4. 根据Score对Comments表对象进行降序排序。

但是当真实执行时候,如下图可以发现执行计划完全不同。

语句已并行方式执行。并且选择了完全不同的执行计划。因为temp表中有很多数据。

引擎决定扫描Comments表上的Score索引。已降序方式从最高扫描到最低。这边列举下主要的差异点:

  1. 预估的执行计划已串行方式执行,但是实际执行计划按照并行方式。
  2. 预估计划使用Comments表的Userid索引,实际计划使用Comments表的Score索引。
  3. 预估计划已temp表开始,实际计划已Comments表为起始。

最后总结造成这种情况的原因是当使用预估方式执行时,MSSQL还没有生成temp表,并且没有任何相关的统计信息。在实际执行时会产生新的统计信息,从而导致MSSQL重新分析,计算执行计划。所以导致预估和实际的有如此大的区别。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论