9

更新:看起来查询不会引发任何超时。连接超时。

这是执行查询的示例代码。有时,在执行耗时的查询时,它会引发超时异常。

不能使用这些技术中的任何一个:1)增加超时。2)使用回调异步运行它。这需要以同步方式运行。

请建议任何其他技术以在执行耗时的查询时保持连接活跃?

private static void CreateCommand(string queryString,
    string connectionString)
{
    using (SqlConnection connection = new SqlConnection(
               connectionString))
    {
        SqlCommand command = new SqlCommand(queryString, connection);
        command.Connection.Open();
        command.ExecuteNonQuery();
    }
}
4

16 回答 16

17

由于您使用的是不返回任何行的 ExecuteNonQuery,因此您可以尝试这种基于轮询的方法。它以异步方式(没有回调)执行查询,但应用程序将等待(在 while 循环内)直到查询完成。来自MSDN。这应该可以解决超时问题。请试一试。

但是,我同意其他人的观点,即您应该更多地考虑优化查询以在 30 秒内执行。

        IAsyncResult result = command.BeginExecuteNonQuery();

        int count = 0;
        while (!result.IsCompleted)
        {
            Console.WriteLine("Waiting ({0})", count++);
            System.Threading.Thread.Sleep(1000);
        }
        Console.WriteLine("Command complete. Affected {0} rows.",
        command.EndExecuteNonQuery(result));
于 2008-09-19T22:33:24.447 回答
4

您应该首先检查您的查询,看看它是否经过优化,并且它没有以某种方式在丢失的索引上运行。大多数查询分配 30 秒,即使在大型数据库上,如果它们经过适当调整。如果您使用查询计划有充分的证据表明查询不能比这更快地执行,那么您应该增加超时,没有其他方法可以保持连接,这就是超时终止连接的目的,如果查询未在该时间范围内完成。

于 2008-09-19T21:33:46.490 回答
1

我必须同意 Terrapin 的观点。

你有几个选择来减少你的时间。首先,如果您的公司雇用 DBA,我建议向他们征求建议。

如果这不是一个选项,或者如果您想先尝试其他一些事情,这里是您的三个主要选项:

  1. 将查询分解为在超时下运行的组件。这可能是最简单的。
  2. 更改查询以优化通过数据库的访问路径(通常:尽可能接近索引)
  3. 更改或添加索引以影响查询的访问路径。
于 2008-09-19T21:28:09.703 回答
1

如果您被限制使用更改超时值的默认过程,您很可能需要做更多的工作。想到以下选项

  1. 与您的 DBA 和另一次代码审查一起验证您是否已经尽可能地优化了查询
  2. 在底层数据库结构上工作,看看您是否可以在数据库方面获得任何收益,创建/修改一个 idex(es)。
  3. 将它分成多个部分,即使这意味着运行具有多个返回参数的过程,这些参数只是调用另一个参数。(这个选项并不优雅,老实说,如果你的代码真的要花这么多时间,我会去管理并重新讨论 30 秒超时)
于 2008-09-19T21:34:35.880 回答
1

我们最近在 SQL Server 2000 数据库上遇到了类似的问题。

在查询期间,在 db 服务器上的主数据库上运行此查询,看看是否有任何锁需要解决:

select 
  spid,
  db_name(sp.dbid) as DBname,
  blocked as BlockedBy,
  waittime as WaitInMs,
  lastwaittype,
  waitresource,
  cpu,
  physical_io,
  memusage,
  loginame,
  login_time,
  last_batch,
  hostname,
  sql_handle
from sysprocesses sp
where (waittype > 0 and spid > 49) or spid in (select blocked from sysprocesses where blocked > 0)

SQL Server Management Studio 2008 还包含一个非常酷的活动监视器,可让您在查询期间查看数据库的运行状况。

在我们的例子中,它是一个使数据库保持忙碌的网络锁。这是一些遗留的 VB 代码,它没有足够快地断开其结果集。

于 2008-09-19T22:23:04.750 回答
1

如果你被禁止使用数据访问 API 的特性让查询持续超过 30 秒,那么我们需要查看 SQL。

与优化 SQL 的收益相比,通过优化 ADO.NET 的使用所获得的性能收益是微不足道的。

而且您已经在使用最有效的 SQL 执行方法。其他技术的速度会慢得多(尽管,如果您使用 DataSet 快速检索行并进行一些非常慢的客户端处理,您可能能够将初始检索时间缩短到 30 秒以下,但我对此表示怀疑。 )

如果我们知道您是否在进行插入,那么也许您应该使用批量插入。但是我们不知道你的sql的内容。

于 2009-05-06T02:49:44.857 回答
1

这是一个 UGLY hack,但可能有助于暂时解决您的问题,直到您可以解决真正的问题

    private static void CreateCommand(string queryString,string connectionString)
    {
        int maxRetries = 3;
        int retries = 0;
        while(true)
        {
            try
            {
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    SqlCommand command = new SqlCommand(queryString, connection);
                    command.Connection.Open();
                    command.ExecuteNonQuery();
                }
                break;
            }
            catch (SqlException se)
            {
                if (se.Message.IndexOf("Timeout", StringComparison.InvariantCultureIgnoreCase) == -1)
                    throw; //not a timeout

                if (retries >= maxRetries)
                    throw new Exception( String.Format("Timedout {0} Times", retries),se);

                //or break to throw no error

                retries++;
            }
        }
    }
于 2009-05-09T14:16:10.433 回答
0
command.CommandTimeout *= 2;

这将使默认超时时间增加一倍,即 30 秒。

或者,将 CommandTimeout 的值放在配置文件中,这样您就可以根据需要调整它而无需重新编译。

于 2008-09-19T21:11:24.500 回答
0

如果您绝对不能增加超时,您唯一的选择是减少查询在默认的 30 秒超时内执行的时间。

于 2008-09-19T21:12:57.417 回答
0

您应该将查询分成多个块,每个块在超时期限内执行。

于 2008-09-19T21:20:21.657 回答
0

我倾向于不喜欢增加连接/命令超时,因为在我看来,这将是处理症状的问题,而不是问题

于 2008-09-19T22:24:31.580 回答
0

只需将 sqlcommand 的 CommandTimeout 属性设置为 0,这将导致命令等待查询完成...例如:

SqlCommand cmd = new SqlCommand(spName,conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
于 2009-05-06T19:36:10.977 回答
0

你有没有想过将查询分解成几个更小的块?

此外,您是否针对以下数据库引擎优化顾问运行了查询:

Management Studio > 工具 > 数据库引擎优化顾问

最后,我们可以看看查询本身吗?

干杯

于 2009-05-12T01:55:12.073 回答
0

您是否尝试过将 sql 包装在存储过程中,它们似乎有更好的内存管理。以前在使用经典 ADO 进行内部查询的计划 sql 语句中看到过这样的超时。即 select * from (select ....) t inner join somthingTable。内部查询返回大量结果的地方。

其他提示 1. 使用 with(nolock) 执行提示执行读取,它很脏,我不推荐它,但它往往会更快。2.还要查看您尝试运行的sql的执行计划并减少行扫描,您加入表的顺序。3. 考虑为您的表添加一些索引以加快读取速度。4. 我还发现删除行非常昂贵,您可以尝试限制每次调用的行数。5. 用#temporary 表交换@table 变量过去也对我有用。6. 你也可能保存了糟糕的执行计划(听说过,没见过)。

希望这可以帮助

于 2009-05-12T06:27:14.907 回答
0

更新:看起来查询不会引发任何超时。连接超时。

Iow,即使您不执行查询,连接也会超时?因为有两个超时:连接和查询。每个人似乎都专注于查询,但是如果您遇到连接超时,那是网络问题,与查询无关:显然,必须先建立连接,然后才能运行查询。

于 2009-05-12T15:33:03.003 回答
0

可能值得尝试将结果分页。

于 2009-10-30T18:05:59.480 回答