如果我在SSMS中运行此命令:
set showplan_xml on
GO
exec some_procedure 'arg1', 'arg2','arg3'
GO
set showplan_xml off
GO
我获得了查询执行中涉及的完整调用堆栈的XML输出,以及任何建议的索引等。
怎么可能从C#中读到这个?
(一个用例可能是定期启用此功能并在生产环境中记录这些结果,以便密切关注索引建议。)
答案 0 :(得分:9)
这在很大程度上是两个独立的(虽然是相关的)问题。
如果您只想 建议的索引(并且不关心执行计划的其余部分),那么您可能最好使用与丢失相关的DMV索引。您只需要编写一些查询而不是应用程序代码。当然,只要服务重新启动,DMV信息就会重置,但如果您希望/需要保留历史记录,则可以将查询结果捕获到表中。有关完整详细信息,请参阅以下MSDN页面:
我可以看到捕获执行计划以获取此信息的唯一好处是它将包含导致建议的查询文本,这显然非常适合进行该研究以确定要实现哪些索引,但是如果查询或查询的许多变体导致相同的建议索引,也可能会爆炸数据行数。请记住一些事情。
是的,这绝对可行,我自己也做过。无论是控制台应用程序,Windows窗体,Web应用程序,SQLCLR等,您都可以在.NET中执行此操作。
以下是您想要捕获XML计划时需要了解的详细信息:
NVARCHAR
/ string
SET SHOWPLAN_XML ON;
SELECT 1
和DECLARE @Bob INT; SET @Bob = 52;
SET STATISTICS XML ON;
SELECT 1
和DECLARE @Bob INT; SET @Bob = 52;
NVARCHAR
类型的单个字段,字段名称为 Microsoft SQL Server 2005 XML Showplan (这一点一致,至少通过SQL Server 2014 ;我还没有测试过SQL Server 2016。)BEGIN TRAN;
/ COMMIT TRAN;
中,以便不会发生实际的数据修改。 SET
命令需要在他们自己的批处理中,所以通过以下方式获取计划:
SqlConnection _Connection = new sqlConnection(_ConnectionStringFromSomewhere);
SqlCommand _Command = _Connection.CreateCommand();
SqlDataReader _Reader = null;
try
{
_Connection.Open();
// SET command needs to be in its own batch
_Command.CommandText = "SET something ON";
_Command.ExecuteNonQuery();
// Now we can run the desired query
_Command.CommandText = _QueryToTest;
_Reader = _Command.ExecuteReader();
..get you some execution plans!
}
finally
{
if (_Reader != null)
{
_Reader.Dispose();
}
_Command.Dispose();
_Connection.Dispose();
}
作为最后一点,我将提到,对于任何有兴趣捕获执行计划但不有兴趣编写任何代码来获取它们的人,我已经将其实现为SQLCLR存储过程。该过程不仅获得了XML执行计划,还获得了STATISTICS TIME
和STATISTICS IO
的输出,这两个输出都很难捕获,因为它们作为消息返回(就像{{1}一样) }语句)。并且,可以将所有3种输出的结果捕获到表格中,以便在多次执行中进行进一步分析(方便进行当前和修订代码的A / B比较)。这可以在SQL# SQLCLR库中找到(我再次,我是其作者)。请注意,虽然有一个免费版本的SQL#,但这个特定的存储过程 DB_GetQueryInfo 仅在完整版本中提供,而不是免费版本。
<强>更新强>
有趣的是,我刚刚浏览了以下MSDN文章,该文章描述了如何使用SQLCLR获取估计的计划,提取估计的成本,将其作为SQLCLR存储过程的OUTPUT参数传回,然后根据它做出决定。我不认为我会将它用于此目的,但鉴于该文章是在2005年撰写的,因此非常有趣: