Pergunta

Atualizar : Parece que a consulta não lançar qualquer timeout. A conexão é o tempo limite.

Este é um código de exemplo para executar uma consulta. Às vezes, durante a execução demorada consultas, ele lança uma exceção tempo limite.

I não pode usar qualquer uma destas técnicas: 1) Aumento do tempo limite. 2) Execute-o de forma assíncrona com um callback. Isso precisa ser executado de forma síncrona.

por favor sugerir quaisquer outras techinques para manter a conexão ativa durante a execução de uma consulta demorada?

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();
    }
}
Foi útil?

Solução

Uma vez que você estiver usando ExecuteNonQuery que não retorna nenhuma linha, você pode tentar este polling abordagem baseada. Ele executa a consulta de forma asyc (sem retorno) mas a aplicação irá esperar (dentro de um ciclo de tempo) até que a consulta é completa. De MSDN . Isto deve resolver o problema de tempo limite. Por favor, experimentá-lo.

Mas, eu concordo com outros que você deve pensar mais sobre como otimizar a consulta para executar menos de 30 segundos.

        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));

Outras dicas

Você deve primeiro verificar sua consulta para ver se ele é otimizado e não é de alguma forma correndo em índices ausentes. 30 segundos é coloc para a maioria das consultas , mesmo em grandes bases de dados, se forem devidamente sintonizados. Se você tem a prova sólida, utilizando o plano de consulta que a consulta não pode ser executado mais rápido do que isso, então você deve aumentar o tempo limite, não há outra maneira de manter a conexão, esse é o propósito do tempo limite para encerrar a conexão se o consulta não for concluída nesse período de tempo.

Eu tenho que concordar com tartaruga de água doce.

Você tem algumas opções sobre como obter o seu tempo para baixo. Em primeiro lugar, se a sua empresa emprega DBAs, eu recomendo pedindo-lhes sugestões.

Se isso não é uma opção, ou se você quiser tentar algumas outras coisas primeiro aqui estão as suas três principais opções:

  1. Quebra-se a consulta em componentes que são executados sob o tempo limite. Este é provavelmente o mais fácil.
  2. Alterar a consulta para otimizar o caminho de acesso através do banco de dados (em geral: bater um índice tão perto quanto possível)
  3. Alterar ou adicionar índices para afetar caminho de acesso de sua consulta.

Se você está impedido de usar o processo padrão de mudar o valor do tempo limite você provavelmente vai ter que fazer muito mais trabalho. As seguintes opções vêm à mente

  1. Validar com o seu DBA e outra revisão de código que você realmente otimizado a consulta da melhor forma possível
  2. O trabalho sobre a estrutura DB subjacente para ver se há qualquer ganho que você pode obter no lado do DB, a criação / modificação de um idex (es).
  3. Divida-o em várias partes, mesmo que isso signifique correr procedimentos com vários parâmetros de retorno que simplesmente chamar outro param. (Esta opção não é elegante, e honestamente se o seu código é realmente vai levar tanto tempo que eu estaria indo para a gestão e o segundo tempo 30 discutir re-)

Nós recentemente teve um problema semelhante em um banco de dados SQL Server 2000.

Durante a sua consulta, executar esta consulta no banco de dados mestre no servidor db e ver se há quaisquer bloqueios que você deve solucionar problemas:

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 também contém um monitor de atividade muito legal que lhe permite ver a saúde do seu banco de dados durante a sua consulta.

No nosso caso, foi um bloqueio NETWORKIO que manteve o banco de dados ocupado. Foi algum código legado VB que não desligue o seu conjunto de resultados bastante rápido.

Se você está proibido de utilizar os recursos da API de acesso de dados para permitir uma consulta para durar mais de 30 segundos, então precisamos ver o SQL.

Os ganhos de desempenho a ser feito através da otimização do uso de ADO.NET são leves em comparação com os ganhos de otimização do SQL.

E você já está usando o método mais eficiente de executar SQL. Outras técnicas seria estarrecedora mais lento (embora, se você fez uma rápida recuperação de suas linhas e alguns side muito lento cliente processamento usando DataSets, você pode ser capaz de obter o baixo recuperação inicial para menos de 30 segundos, mas eu duvido. )

Se soubéssemos se você estivesse fazendo inserções, então talvez você deve estar usando inserção em massa. Mas nós não sabemos do conteúdo do seu sql.

Esta é uma gambiarra, mas podem ajudar a resolver o seu problema temporariamente até que você pode corrigir o problema real

    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++;
            }
        }
    }
command.CommandTimeout *= 2;

Isso irá duplicar o tempo limite padrão, que é de 30 segundos.

Ou, colocando o valor de CommandTimeout em um arquivo de configuração, para que possa ajustá-lo conforme necessário, sem recompilação.

Você deve quebrar sua consulta-se em vários pedaços que cada executar dentro do tempo limite.

Se você absolutamente não pode aumentar o tempo limite, a sua única opção é reduzir o tempo da consulta para executar dentro do segundo tempo limite padrão de 30.

I tendem a não gostar aumentar o tempo limite de conexão / command uma vez que em minha mente que seria uma questão de cuidar do sintoma, não o problema

você já pensou em quebrar a consulta para baixo em vários pedaços menores?

Além disso, você já correu sua consulta contra o Database Engine Tuning Advisor em:

Management Studio> Ferramentas> Database Engine Tuning Advisor

Por fim, poderíamos obter um olhar para a própria consulta?

aplausos

Você tentou envolver o seu SQL dentro de um procedimento armazenado, eles parecem ter melhor gerenciamento de memória. Ter visto o tempo limite como este antes em plano de instrução SQL com consultas internas usando ADO clássico. isto é, seleccionar a partir de * (seleccionar ....) t junção interna somthingTable. Onde a consulta interna estava retornando um número muito grande de resultados.

Outras dicas 1. Performing lê com a dica de execução com (nolock), é sujo e eu não recomendo, mas ele tenderá a ser mais rápido. 2. Também olhar para o plano de execução do sql sua tentativa de correr e reduzir a varredura linha, a ordem em que você participar de mesas. 3. olhada adicionando alguns índices de suas tabelas para uma mais rápida lê. 4. Descobri também que a exclusão de linhas é muito caro, você poderia tentar limitar o número de linhas por chamada. 5. Troque variáveis ??@Table com mesas #temporary também tem trabalhado para mim no passado. 6. Você também pode ter salvo plano de execução ruim (ouvi, nunca visto).

Espero que isso ajude

Atualização: Parece que a consulta não jogar qualquer limite de tempo. A conexão é o tempo limite.

I.o.w., mesmo se você não executar uma consulta, a conexão expira? porque há dois limites de tempo: conexão e consulta. Todo mundo parece se concentrar na consulta, mas se o tempo limite de conexão, é um problema de rede e não tem nada a ver com a consulta: primeiro a ligação tem de ser estabelecida antes de uma consulta pode ser executado, obviamente.

Pode valer a pena tentar paginação os resultados de volta.

CommandTimeout propriedade apenas conjunto de SqlCommand a 0, isso fará com que o comando que esperar até o término da consulta ... por exemplo:

SqlCommand cmd = new SqlCommand(spName,conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top