Uma varredura constante leva 0 segundos ou 2-3 minutos

9

Uma consulta como a abaixo, garantida para não retornar nenhuma linha, leva de 0 a 160 segundos em um de nossos servidores:

select col1, col2, col3
from tab1
where 0 = 1

Duas semanas atrás, isso aconteceu seis vezes em um intervalo de 48 horas. Na semana passada, a mesma consulta levou ~ 0 segundos. Eu tenho logs dos SQLs do nosso aplicativo, mas ainda não encontrei nenhum suspeito. Além disso, eu pensei que uma consulta do tipo 0 / onde 0 = 1 nunca atingiu as páginas de dados, por isso deve ser resistente a bloqueios de dados de linha / página / tabela? O esquema não é tocado por nenhum SQL (conhecido).

Como o problema não é consistente e o servidor está sob uma carga muito pesada, eu gostaria de entender a teoria por trás do que está acontecendo antes de anexar o criador de perfil SQL. Outras consultas são executadas sem problemas durante esses atrasos. Um problema conhecido no aplicativo é um alto número de consultas SQL criadas dinamicamente - cerca de 200 mil consultas exclusivas de 850 mil consultas totais (registradas) durante um período de 48 horas, isso pode causar problemas como este?

O servidor está executando o SQL Server 2005 standard edition, 96 GB de RAM, discos na SAN e 4 CPUs / 16 núcleos. Os arquivos e grupos de arquivos do banco de dados estão bem otimizados e não devem ser um problema (mas estamos analisando isso separadamente).

Qualquer indicação para onde procurar é muito apreciada.

Edit: Perfeito! Reproduziu a consulta para adicionar o plano de execução e levou 1 minuto e 35 segundos. Aqui está o plano de execução e a captura de tela mostrando a duração da consulta: Plano de consulta

Editar 2: detalhes do tempo das estatísticas para uma segunda execução. Parece ser consistentemente lento no momento, então anexaremos o profiler e o perfmon:

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 97402 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.
Horizonte de eventos
fonte
Você poderia incluir o plano de execução? CTRL + M na janela de consulta antes da execução.
Craig Efrein 17/03/14
2
Poderia ser um problema de bloqueio? Instruções DML de outras sessões que bloqueiam a seleção na tabela (que é o comportamento padrão no SQL Server 2005)
a_horse_with_no_name
Não existem instruções DML conhecidas, que é a única causa em que consigo pensar, mas ainda estamos investigando isso. O plano de execução é adicionado à pergunta.
EventHorizon
Pelo que tenho lido, este é apenas um dos planos de execução triviais que MSSQL usa para evitar a leitura montes e índices quando o otimizador sabe não há linhas a serem devolvidos
Craig Efrein
11
Vi um caso que se parecia muito com isso. Acabou provocando estatísticas de atualização (estatísticas de atualização automática foram ativadas e o plano de manutenção foi interrompido).
Joshua

Respostas:

18

Parece que, mesmo com uma ... WHERE 0 = 1cláusula, ainda haverá um requisito para um ISbloqueio de intenção shared ( ) na tabela. Vamos provar isso:

Vou começar criando uma tabela de teste:

use TestDb1;
go

create table dbo.MyTestTable1
(
    Id int identity(1, 1) not null,
    SomeInt int not null
);
go

insert into dbo.MyTestTable1 (SomeInt)
values (10), (20), (30), (40), (50);
go

Agora que tenho minha tabela de teste, em uma sessão (janela de consulta) vou executar o seguinte para colocar um Xbloqueio exclusivo ( ) dbo.MyTestTable1:

use TestDb1;
go

begin tran;
    select
        Id, SomeInt
    from dbo.MyTestTable1 with (tablockx);
--commit tran;

Eu posso verificar o bloqueio exclusivo olhando para o sys.dm_tran_locksDMV. Em outra sessão (nova janela de consulta), faço exatamente o que sua consulta faz:

use TestDb1;
go

select
    Id, SomeInt
from dbo.MyTestTable1
where 0 = 1;

À primeira vista, vejo que não está terminando. Olhando sys.dm_exec_requests, vejo exatamente por que esse é o caso:

select
    r.session_id,
    r.status,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    r.blocking_session_id
from sys.dm_exec_requests r
cross apply sys.dm_exec_sql_text(r.sql_handle) st
where st.text like '%where 0 = 1%'
and r.session_id <> @@spid;

insira a descrição da imagem aqui

Eu posso ver aqui que minha ... WHERE 0 = 1consulta está aguardando um ISbloqueio para esse objeto (que object_id traduz para dbo.MyTestTable1).

Não estou dizendo que a simultaneidade é um problema seu , mas pelos sons dela você está exibindo os sintomas. O exemplo acima é para provar que você não está isento de bloqueio e bloqueio, mesmo com uma WHEREcláusula que nunca retornará dados.

Tudo o que podemos fazer é adivinhar, então o que você precisa fazer quando está "demorando muito" é ver exatamente o que essa solicitação está fazendo e que está demorando tanto. Se estiver esperando algo, veja o que está esperando.

Thomas Stringer
fonte
1

Dependendo do nível de picos e de threads que exigem suas consultas, seu sistema pode simplesmente estar na fila dessa consulta. A contagem padrão de trabalhadores (ou seja, número de threads simultâneos do servidor SQL) para sua instalação deve ser de cerca de 700.

Confira sys.dm_os_schedulers e sys.dm_os_waiting_tasks para ver se isso pode ser um problema.

Sascha Rambeaud
fonte
Uma boa sugestão, mas o problema acabou sendo um bloqueio bobo, afinal.
EventHorizon
Eu não estava realmente convencido, desde 700 trabalhadores é muito, mas era fácil de verificar (e, portanto, excluir)
Sascha Rambeaud