使用视图连接表或存储过程以获得更好的执行计划?

Dib*_*Dib 3 performance sql-server stored-procedures execution-plan view query-performance

首先让我声明我是 C# 开发人员,而不是 SQL Server DBA,所以请原谅我对 SQL Server 数据库查询执行计划的无知。

我想知道的是对于使用主键和外键从两个或多个表中提取结果以引用它们的存储过程,是否更好的做法是:

  1. 有一个视图,视图执行连接并包含两个(或多个)表中所有相应记录的扁平化数据,并让存储过程从该视图中进行选择和过滤
  2. 存储过程进行连接和过滤

我问是因为在 C# 世界中,我们会将关注点分开,因此一个对象或函数将负责连接(在本例中为视图),另一个对象或函数将负责过滤(在本例中为存储过程) )。

  • 上面哪个选项会表现得更好?
  • 上面的哪个选项被认为是最佳实践?

在 C# 中,关注点分离通常被认为比性能更重要,直到证明性能已成为代码的严重问题。但是我不知道SQL世界里的东西堆起来了!

Pau*_*ite 5

上面哪个选项会表现得更好?

最好的情况是,两者将产生完全相同的执行计划,具有相同的运行时性能。

正如 Rob Farley 在他的回答中提到的,这可能需要一些仔细的设计和一些相当高级的技能。Rob 也有一篇博客文章描述了核心问题,并且在他的SQL Server MVP Deep Dives Volume 1书中的一章中也讨论了这个问题。

上面的哪个选项被认为是最佳实践?

这可能更多是一种意见问题,而不是既定的最佳实践,但经验丰富的数据库专业人员倾向于将他们对视图的使用限制在他们提供真正和显着好处的场景中。视图变得越复杂(尤其是当视图开始堆积或分层时),避免不良副作用的难度就越大,遇到优化器限制的可能性就越大。

如果查询引用一个视图,它可能更易于阅读和维护,但“关注点分离”并不是您在选择视图或在存储过程中编写底层查询时数据库专业人员讨论的事情。编程中有许多既定的实践和模式并不能很好地转化为数据库工作。

始终牢记(非索引/物化)视图只是一个存储的查询定义。它被扩展到引用查询中,就像在查询编译和优化开始之前手动复制粘贴一样。

您没有要求对使用视图的优点和缺点进行全面批评(无论如何,这可能是一个太宽泛的问题),因此我不会尝试提供。我最后要告诫的是,即使是今天优化得很好的简单视图(也许利用了 Rob 的想法)也可以很容易地修改(通常以一种无害的方式),因此引用它们的查询会突然遇到优化器限制和性能悬崖。