Estamos usando o SQL Server 2008 R2 e temos uma tabela muito grande (100M + linhas) com um índice de identificação primário e uma datetimecoluna com um índice não clusterizado. Estamos vendo um comportamento cliente / servidor altamente incomum, com base no uso de uma order bycláusula especificamente em uma coluna de data e hora indexada .
Eu li o seguinte post: /programming/1716798/sql-server-2008-ordering-by-datetime-is-too-slow, mas há mais coisas acontecendo com o cliente / servidor do que o que é comece descrito aqui.
Se executarmos a seguinte consulta (editada para proteger algum conteúdo):
select *
from [big table]
where serial_number = [some number]
order by test_date desc
A consulta atinge o tempo limite sempre. No SQL Server Profiler, a consulta executada se parece com isso no servidor:
exec sp_cursorprepexec @p1 output,@p2 output,NULL,N'select * .....
Agora, se você modificar a consulta, diga o seguinte:
declare @temp int;
select * from [big table]
where serial_number = [some number]
order by test_date desc
O SQL Server Profiler mostra que a consulta executada se parece com isso para o servidor e FUNCIONA instantaneamente:
exec sp_prepexec @p1 output, NULL, N'declare @temp int;select * from .....
Por uma questão de fato, você pode até colocar um comentário vazio ('-;') em vez de uma declaração de declaração não utilizada e obter o mesmo resultado. Portanto, inicialmente apontamos o pré-processador sp como a causa raiz desse problema, mas se você fizer isso:
select *
from [big table]
where serial_number = [some number]
order by Cast(test_date as smalldatetime) desc
Também funciona instantaneamente (você pode convertê-lo como qualquer outro datetimetipo), retornando o resultado em milissegundos. E o criador de perfil mostra a solicitação ao servidor como:
exec sp_cursorprepexec @p1 output, @p2 output, NULL, N'select * from .....
Portanto, isso exclui o sp_cursorprepexecprocedimento da causa completa do problema. Adicione a isso o fato de que sp_cursorprepexectambém é chamado quando nenhum 'pedido por' é usado e o resultado também é retornado instantaneamente.
Pesquisamos bastante esse problema no Google, e vejo problemas semelhantes publicados por outros, mas nenhum que o reduza a esse nível.
Então, outras pessoas testemunharam esse comportamento? Alguém tem uma solução melhor do que colocar SQL sem sentido na frente da instrução select para mudar o comportamento? Como o SQL Server deve chamar a ordem após a coleta dos dados, parece que esse é um erro no servidor que persiste por um longo tempo. Nós descobrimos que esse comportamento é consistente em muitas de nossas tabelas grandes e é reproduzível.
Editar% s:
Devo acrescentar que colocar um forceseektambém faz o problema desaparecer.
Devo adicionar para ajudar os pesquisadores, o erro de tempo limite do ODBC lançado é: [Microsoft] [Driver do ODBC SQL Server] Operação cancelada
Adicionado em 12/10/2012: Ainda em busca da causa raiz (além de ter construído uma amostra para fornecer à Microsoft, cruzarei os resultados aqui após o envio). Venho pesquisando no arquivo de rastreamento ODBC entre uma consulta de trabalho (com uma declaração de comentário / declaração) e uma consulta que não está funcionando. A diferença fundamental de rastreamento está publicada abaixo. Ocorre na chamada para a chamada SQLExtendedFetch após a conclusão de todas as discussões SQLBindCol. A chamada falha com o código de retorno -1 e o encadeamento pai entra no SQLCancel. Como somos capazes de produzir isso com os drivers ODBC do cliente nativo e herdado, ainda estou apontando para algum problema de compatibilidade no lado do servidor.
(clip)
MSSQLODBCTester 1664-1718 EXIT SQLBindCol with return code 0 (SQL_SUCCESS)
HSTMT 0x001EEA10
UWORD 16
SWORD 1 <SQL_C_CHAR>
PTR 0x03259030
SQLLEN 51
SQLLEN * 0x0326B820 (0)
MSSQLODBCTester 1664-1718 ENTER SQLExtendedFetch
HSTMT 0x001EEA10
UWORD 1 <SQL_FETCH_NEXT>
SQLLEN 1
SQLULEN * 0x032677C4
UWORD * 0x032679B0
MSSQLODBCTester 1664-1fd0 ENTER SQLCancel
HSTMT 0x001EEA10
MSSQLODBCTester 1664-1718 EXIT SQLExtendedFetch with return code -1 (SQL_ERROR)
HSTMT 0x001EEA10
UWORD 1 <SQL_FETCH_NEXT>
SQLLEN 1
SQLULEN * 0x032677C4
UWORD * 0x032679B0
DIAG [S1008] [Microsoft][ODBC SQL Server Driver]Operation canceled (0)
MSSQLODBCTester 1664-1fd0 EXIT SQLCancel with return code 0 (SQL_SUCCESS)
HSTMT 0x001EEA10
MSSQLODBCTester 1664-1718 ENTER SQLErrorW
HENV 0x001E7238
HDBC 0x001E7B30
HSTMT 0x001EEA10
WCHAR * 0x08BFFC5C
SDWORD * 0x08BFFF08
WCHAR * 0x08BFF85C
SWORD 511
SWORD * 0x08BFFEE6
MSSQLODBCTester 1664-1718 EXIT SQLErrorW with return code 0 (SQL_SUCCESS)
HENV 0x001E7238
HDBC 0x001E7B30
HSTMT 0x001EEA10
WCHAR * 0x08BFFC5C [ 5] "S1008"
SDWORD * 0x08BFFF08 (0)
WCHAR * 0x08BFF85C [ 53] "[Microsoft][ODBC SQL Server Driver]Operation canceled"
SWORD 511
SWORD * 0x08BFFEE6 (53)
MSSQLODBCTester 1664-1718 ENTER SQLErrorW
HENV 0x001E7238
HDBC 0x001E7B30
HSTMT 0x001EEA10
WCHAR * 0x08BFFC5C
SDWORD * 0x08BFFF08
WCHAR * 0x08BFF85C
SWORD 511
SWORD * 0x08BFFEE6
MSSQLODBCTester 1664-1718 EXIT SQLErrorW with return code 100 (SQL_NO_DATA_FOUND)
HENV 0x001E7238
HDBC 0x001E7B30
HSTMT 0x001EEA10
WCHAR * 0x08BFFC5C
SDWORD * 0x08BFFF08
WCHAR * 0x08BFF85C
SWORD 511
SWORD * 0x08BFFEE6
(clip)
Foi adicionado um caso do Microsoft Connect em 10/10/2012:
Devo também observar que procuramos os planos de consulta para as consultas funcionais e não funcionais. Ambos são reutilizados adequadamente com base na contagem de execução. Esvaziar os planos em cache e executar novamente não altera o sucesso da consulta.
sp_executesqle veja o que acontece.
select id, test_date from [big table] where serial_number = ..... order by test_date- eu só estou me perguntando se issoSELECT *tem um impacto negativo no seu desempenho. Se você tem um índice sem cluster emtest_datee um índice agrupado naid(assumindo que é o que é chamado), esta consulta deve ser coberta por esse índice agrupado e, portanto, deve retornar muito rapidamente