SqlCommand.Cancel()会提升性能吗?

我已经看到这在代码中显示了几个地方,从来没有解释,只是上面的一个神秘的评论(声明和执行包含在上下文的想法。它只是运行SqlCommand的标准过程):

//SqlCommand cmd = new SqlCommand(); //cmd.ExecuteReader(); //Read off the results //Cancel the command. This improves query time. cmd.Cancel (); 

基本上,在完成一个查询之后,它会返回并取消它,声称会有一些性能提升。 我想你可能会获得一些内存,并释放XmlReader,但通常情况下它会超出范围。

我之前从未打扰过它,但它最终出现在我正在审查的一些代码中。 在代码中运行它后取消SqlCommand实际上是以某种方式加速它,还是这只是一些奇怪的程序员迷信?

根据MSDN ,这是正确的。

Close方法填充输出参数,返回值和RecordsAffected的值,从而增加了关闭用于处理大型或复杂查询的SqlDataReader所需的时间。 当返回值和受查询影响的记录数不重要时,可以通过在调用Close方法之前调用关联的SqlCommand对象的Cancel方法来减少关闭SqlDataReader所需的时间。

奇怪的!

如果对ExecuteReader的调用返回大量行,并且您没有读取所有行,则调用Cancel 提高潜在的MASSIVE性能

为了说明,假设一个查询返回一百万行,并在读取前1000行后关闭阅读器。 如果在关闭阅读器之前未能调用Cancel ,则Close方法将在内部枚举剩余的999,000行时阻止

试试看吧!

我们在Cinchcast的技术团队进行了一些基准测试,我们发现添加cmd.Cancel()实际上会降低它的速度。

我们有一个DALC调用,可以获取主机的剧集列表。 我们运行了1000次并获得了平均响应时间以返回10集。

所以返回10个节目平均有取消:0.069平均没有取消:0.026s

在回归10集的情况下跑步时速度相当慢。

因此,我再次尝试返回100集,以查看更大的结果集是否有所作为。

因此,每次通话返回100个节目平均值取消:0.132s平均无取消:0.122s

所以这次时间的差异要小得多。 虽然没有使用取消作为我们通常的用例,但它仍然更快。

在您的示例中,您打开阅读器,阅读所有行和取消命令,但您没有显示阅读器被关闭的位置。

确保取消发生 Dispose / Close 之前 。 例如,您不会在此示例中获得性能提升(不幸的是,生产中的实际代码):

 using (var rdr = cmd.ExecuteReader (CommandBehavior.Default)) { retval = DocumentDir.DBRead (rdr); } // Optimization. Allows reader to close more quickly.... NOT! cmd.Cancel (); // bad! 

太糟糕了,它已经被使用声明关闭了!

这是它应该如何阅读以实现潜在的好处:

 using (var rdr = cmd.ExecuteReader (CommandBehavior.Default)) { retval = DocumentDir.DBRead (rdr); // Optimization. Allows reader to close more quickly. cmd.Cancel (); } 

从MSDN SqlCommand.Cancel :

在某些罕见情况下,如果调用ExecuteReader然后在调用Cancel之前调用Close(隐式或显式),然后调用Cancel,则取消命令将不会发送到SQL Server,并且结果集可以在调用Close后继续流式传输。 为避免这种情况,请确保在关闭阅读器或连接之前调用取消。