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

发布于 2024-09-14 22:21:04 字数 448 浏览 1 评论 0原文

我已经看到它出现在代码中的多个位置,从来没有解释,只是上面有一个神秘的注释(声明和执行包括上下文概念。这只是运行 SqlCommand 的标准过程):

//SqlCommand cmd = new SqlCommand();
//cmd.ExecuteReader();
//Read off the results

//Cancel the command. This improves query time.
cmd.Cancel ();

基本上,在完成查询后,它返回并取消它,声称性能有所提升。我想当它消失并释放 XmlReader 时您可能会收回一些内存,但通常它无论如何都会超出范围。

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

I have seen this show up several places in code, never with an explanation, just a cryptic comment above it (Declaration and execution included for an idea of context. It's just a standard procedure of running a SqlCommand):

//SqlCommand cmd = new SqlCommand();
//cmd.ExecuteReader();
//Read off the results

//Cancel the command. This improves query time.
cmd.Cancel ();

Basically, after finishing a query, it goes back and cancels it, claiming some performance boost. I suppose you might get some memory back when it goes and frees up the XmlReader, but usually it's about to go out of scope anyways.

I've never bothered with it before, but it's finally showed up in some code I'm reviewing. Does canceling a SqlCommand after running it in the code actually somehow speed it up, or is this just some weird programmer superstition?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

偏爱你一生 2024-09-21 22:21:04

根据 MSDN,这是正确的。

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

诡异的!

According to MSDN, this is correct.

The Close method fills in the values
for output parameters, return values
and RecordsAffected, increasing the
time that it takes to close a
SqlDataReader that was used to process
a large or complex query. When the
return values and the number of
records affected by a query are not
significant, the time that it takes to
close the SqlDataReader can be reduced
by calling the Cancel method of the
associated SqlCommand object before
calling the Close method.

Weird!

节枝 2024-09-21 22:21:04

如果您调用 ExecuteReader 返回大量行,并且您不读取数据,则调用 Cancel 可能会大幅提高性能所有行。

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

尝试看看!

Calling Cancel gives a potentially MASSIVE performance improvement if your call to ExecuteReader returns a large number of rows, and you don't read all the rows.

To illustrate, let's say a query returns a million rows, and you close the reader after reading just the first 1000 rows. If you fail to call Cancel before closing the reader, the Close method will block while it internally enumerates through the remaining 999,000 rows

Try it and see!

遇到 2024-09-21 22:21:04

我们 Cinchcast 的技术团队做了一些基准测试,我们发现添加 cmd.Cancel() 实际上会减慢速度。

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

所以返回 10 场演出
平均取消时间:0.069s
没有取消的平均:0.026s

当返回 10 集运行时速度明显慢一些。

因此,我再次尝试返回 100 集,看看更大的结果集是否会产生影响。

因此每次调用都会返回 100 个节目
平均取消时间:0.132s
没有取消的平均时间:0.122s

所以这次时间差异要小得多。尽管在我们通常的用例中不使用“取消”,但它仍然更快。

Our Tech team at Cinchcast did some benchmarking, and we have found that adding the cmd.Cancel() actually slows it down.

We have a DALC call that gets a list of episodes for a host.
We ran it 1000 times and got the average response time to return 10 episodes.

So with returning 10 shows
Average With Cancel: 0.069s
Average Without Cancel : 0.026s

Pretty significantly slower when running with returning 10 episode.

So, I tried again with returning 100 episodes to see if a larger result set makes a difference.

So with returning 100 shows on each call
Average With Cancel: 0.132s
Average Without Cancel : 0.122s

So this time the difference in time was much less. It is still faster though without using the Cancel for our usual use cases.

不喜欢何必死缠烂打 2024-09-21 22:21:04

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

确保取消发生在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语句关闭了!

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

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 后进行流式传输。为了避免这种情况,请确保在关闭读取器或连接之前调用 Cancel。

In your example, you open the reader, read all the rows, and the Cancel the command, but you didn't show where the reader was being closed.

Make sure the canceling happens before the Dispose/Close. For example, you wouldn't get a performance boost in this example (real code in production, unfortunately):

using (var rdr = cmd.ExecuteReader (CommandBehavior.Default))
{
   retval = DocumentDir.DBRead (rdr);
}

// Optimization.  Allows reader to close more quickly.... NOT!
cmd.Cancel ();  // bad!

Too bad it's already closed by the Using Statement!

This is how it should read to realize the potential benefit:

using (var rdr = cmd.ExecuteReader (CommandBehavior.Default))
{
   retval = DocumentDir.DBRead (rdr);

   // Optimization.  Allows reader to close more quickly.
   cmd.Cancel ();
}

From MSDN SqlCommand.Cancel:

In some, rare, cases, if you call ExecuteReader then call Close (implicitily or explicitly) before calling Cancel, and then call Cancel, the cancel command will not be sent to SQL Server and the result set can continue to stream after you call Close. To avoid this, make sure that you call Cancel before closing the reader or connection.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文