我正在执行我在本网站标记所有表和存储过程以进行重新编译。
(我将其更改为标记存储过程)
我有一个 Windows 窗体(.net 3.5)应用程序,它使用了大量的数据表,执行此脚本后,打开数据量大的表单所需的时间从 8 秒缩短到仅 4 秒。
我是否必须定期运行这样的脚本?我以为 SQL Server 会负责编译程序等。
顺便说一句:这个问题应该在 SO 上吗?我以为 DBA 会在 SF 上。
答案1
从微软:
“当数据库因添加索引或更改索引列中的数据等操作而发生变化时,用于访问其表的原始查询计划应通过重新编译再次进行优化。在 Microsoft SQL Server 重新启动后第一次运行存储过程时,会自动进行此优化。如果存储过程使用的底层表发生变化,也会发生这种情况。但如果添加了存储过程可能受益的新索引,则优化要等到 Microsoft SQL Server 重新启动后下次运行存储过程时才会发生。在这种情况下,强制存储过程在下次执行时重新编译会很有用
强制重新编译存储过程的另一个原因是,在必要时抵消存储过程编译的“参数嗅探”行为。当 SQL Server 执行存储过程时,过程在编译时使用的任何参数值都将包含在生成查询计划中。如果这些值代表随后调用过程的典型值,则存储过程每次编译和执行时都会从查询计划中受益。如果不是,性能可能会受到影响。”
答案2
考虑一下 SQL Server 中“编译”一词的使用与普通应用程序不同。在普通应用程序中,代码被编译为机器语言就绪状态,因此不必在运行时进行解释。SQL Server 使用编译来确定执行查询的最佳执行计划。由于数据可能会不断变化,SQL Server 可能必须根据可用的索引、统计信息的质量等做出新的决定,所有这些都会影响执行计划。因此,每当执行存储过程时,SQL Server 都会确定是否可以为该查询重新使用现有的执行计划,或者是否需要生成新的执行计划。当然,如果不存在计划,它将生成一个新的计划。
顺便说一句,如果你仔细想想,这与 .NET 应用程序所做的并没有太大区别。.NET 应用程序被编译为中间语言状态,但仅在第一次运行时默认完全编译。
答案3
当 SP 被编译时,它的执行路径是固定的。它不能利用新的索引,或基于表大小的不同策略。重新编译允许它重新评估执行条件。
我在这方面没有太多经验 - 但经验法则是让简单的 SP 每次都重新编译。仅在更复杂的情况下才设置不编译