.NET 应用程序使用的 SQL 视图超时
Posted
技术标签:
【中文标题】.NET 应用程序使用的 SQL 视图超时【英文标题】:SQL View timing out used by .NET Application 【发布时间】:2017-02-22 03:29:40 【问题描述】:我们有一个 .NET 应用程序,它使用 LINQ to SQL (ORM) 来调用一个视图,该视图包含来自不同数据库中多个对象的连接。 .NET 应用程序调用此视图超时,但我们的 DBA 运行以下语句:
sp_refreshview on the view and the subsequennt sql views
应用程序再次开始运行。
此应用程序在接近 20 分钟后再次在同一视图上开始超时。所以我们的 DBA 已经安排了一个作业,每 30 分钟运行一次上述语句。视图没有发生结构性变化,我们正试图弄清楚为什么 sp_refreshview
修复了这个问题,以及我们可以修复的潜在问题是什么?
【问题讨论】:
视图是否包含任何内联函数?没有.net之类的层直接运行时执行需要多长时间?所以通过管理工作室等...... 视图不包含任何内联函数。当 sp_refresh 完成后,直接通过 .net 或 sql management studio 运行时,查看只需要几毫秒。如果 sp_refresh 没有完成,视图仍然只能在几毫秒内从 sql server 运行,但从 .net 运行时会超时 @user1490835,您的最后一条评论听起来与我刚才在回答中指出的 Erland Sommarskog 的文章 Slow in the Application, Fast in SSMS 的标题完全相同。您是否阅读并检查过该问题与该文章中讨论的问题是否不同? @VladimirBaranov,我确实看过这篇文章,其中没有我们不知道或尝试过的内容。我也把它交给了我们的 DBA,但那里没有任何积极的反馈。但是无论如何我都会奖励你赏金,因为这似乎是最有用的答案(每个答案/评论都很有用)但由于问题仍然存在,我不会将其标记为答案。 谢谢@user1490835。不幸的是,我没有任何其他想法。我会尝试确认是否有两种不同的执行计划——“慢”和“快”。如果是,那么看看你能做些什么来防止服务器生成“慢”计划。如果应用程序和 SSMS 的计划相同,则检查应用程序以找出有时查询缓慢的原因。 【参考方案1】:sp_refreshview
解决问题的原因是视图不受模式限制。 SQLServer 保留有关视图的元数据以帮助执行,并且由于视图不受模式绑定,因此元数据会随着基础对象的更新而过时(想想 DML 语句)。 sp_refreshview
所做的是更新非模式绑定视图的元数据,以便它们能够以最佳方式运行。看看documentation 的sp_refreshview
。
要弄清楚为什么会这样,请考虑一下什么是视图?视图只是一个查询。存储的元数据与该查询相关。
每当您运行查询时,服务器都会找出运行该查询的最佳方式(称为计划),这取决于查询中使用的表的统计信息。随着表中的数据发生变化,表的统计信息也会发生变化,因此计划也会发生变化。当您创建视图(非模式绑定)时,将存储围绕最佳执行的元数据(很可能是计划)。由于视图只是一个查询,因此计划可能会过时,sp_refreshview
会更新该元数据。
【讨论】:
好的,但问题是视图内部没有更新。过去2年的观点是一样的。没有 DML 声明...没有任何与视图相关的内容被触及。在发布此问题之前,我们确实查看了文档,目前除了它正在工作之外没有什么意义 构成视图的基础数据在 2 年内没有变化?视图本身并没有发生变化,而是表中的数据构成了将要发生变化的视图。 但这将如何改变视图周围的元数据? 问题是如果我们更新统计信息并忽略视图刷新(sp_refreshview)仍然超时如果你说的是正确的,那么更新统计信息肯定会优化执行计划从而调整视图......但是那不是这样的 如果你想要修复,你需要架构绑定你的视图。否则,您将需要定期运行sp_refreshview
以获得最佳性能。【参考方案2】:
很可能sp_refreshview
导致服务器从缓存中删除缓存的查询执行计划。当您在调用sp_refreshview
后运行查询时,会生成新的(更好的)执行计划。这就是为什么调用sp_refreshview
会有所帮助。显然,更新统计信息不会删除缓存的执行计划,这就是为什么它对您的情况没有帮助。
有些类型的查询无法为所有可能的参数值制定一个好的计划,或者您的数据可能会严重倾斜。
如果您将OPTION(RECOMPILE)
添加到您的查询中,您很可能不需要调用sp_refreshview
来使其快速运行。
当你的 ORM 生成查询时,我不知道如何添加这个查询提示。
我建议您阅读 Erland Sommarskog 的一篇出色的文章 Slow in the Application, Fast in SSMS。
【讨论】:
它不工作。还有其他建议吗?有没有办法在 sp_Refreshview 存储过程中获取 sql? @user1490835,我会尝试使用 SQL Profiler 查看sp_refreshview
运行时执行了哪些查询。
根据我在 Google 上的了解和阅读以及与我们的 DBA 聊天后,SQL Server 似乎没有为视图创建查询计划。
@user1490835,当然,它不会为视图创建执行计划。它为通过视图访问表的实际查询创建执行计划。我的猜测是,在您的情况下,这些执行计划在 20 分钟后变得非最优。 sp_refreshview
将导致服务器删除为使用视图进行查询而构建的所有缓存计划。您应该能够通过不首先使用OPTION(RECOMPILE)
缓存计划来实现相同的效果。 ...
@user1490835,另一方面,如果您说OPTION(RECOMPILE)
对您没有帮助,那么我猜sp_refreshview
导致服务器删除缓存的计划是错误的。或者问题与非最优计划无关。为了确认,我会尝试在查询快速运行时获取执行计划,然后在相同查询在 20 分钟内运行缓慢时获取执行计划并进行比较。【参考方案3】:
元数据是关于视图使用的表的信息。统计信息更新有关数据的信息。查看您的视图定义可能会有所帮助。例如,在视图中有一个 select * 可能真的会给你带来问题。作为复习,视图只是一个语句,直到它被执行。如果您使用的表总是在更改其结构或被删除并重新添加,则每次都需要运行 sp_refreshview。如果您需要其他帮助,您将需要提供查询和有关基础表的任何信息,例如处理刷新它们。上述所有 cmets 都在合理范围内正确。
【讨论】:
以上是关于.NET 应用程序使用的 SQL 视图超时的主要内容,如果未能解决你的问题,请参考以下文章
如何调查 ASP.net 应用程序上的 SQL Server 超时错误?
Sql Server Profiler 跟踪在 Web 应用程序中给出超时