Estamos utilizando SQL Server 2008 R2 y tenemos una tabla muy grande (más de 100 millones de filas) con un índice de identificación principal y una datetime
columna con un índice no agrupado. Estamos viendo un comportamiento de cliente / servidor muy inusual basado en el uso de una order by
cláusula específicamente en una columna de fecha y hora indexada .
Leí la siguiente publicación: /programming/1716798/sql-server-2008-ordering-by-datetime-is-too-slow pero hay más cosas con el cliente / servidor de lo que es Comience descrito aquí.
Si ejecutamos la siguiente consulta (editada para proteger algún contenido):
select *
from [big table]
where serial_number = [some number]
order by test_date desc
La consulta agota el tiempo de espera cada vez. En el SQL Server Profiler, la consulta ejecutada se ve así para el servidor:
exec sp_cursorprepexec @p1 output,@p2 output,NULL,N'select * .....
Ahora, si modifica la consulta a, diga esto:
declare @temp int;
select * from [big table]
where serial_number = [some number]
order by test_date desc
El SQL Server Profiler muestra que la consulta ejecutada se ve así para el servidor, y FUNCIONA instantáneamente:
exec sp_prepexec @p1 output, NULL, N'declare @temp int;select * from .....
De hecho, incluso puede poner un comentario vacío ('-;') en lugar de una declaración de declaración no utilizada y obtener el mismo resultado. Inicialmente, apuntamos al preprocesador sp como la causa principal de este problema, pero si hace esto:
select *
from [big table]
where serial_number = [some number]
order by Cast(test_date as smalldatetime) desc
Funciona instantáneamente también (puede lanzarlo como cualquier otro datetime
tipo), devolviendo el resultado en milisegundos. Y el generador de perfiles muestra la solicitud al servidor como:
exec sp_cursorprepexec @p1 output, @p2 output, NULL, N'select * from .....
Eso excluye un poco el sp_cursorprepexec
procedimiento de la causa completa del problema. Agregue a esto el hecho de que sp_cursorprepexec
también se llama cuando no se usa 'ordenar por' y el resultado también se devuelve instantáneamente.
Hemos buscado en Google este problema bastante, y veo problemas similares publicados por otros, pero ninguno lo desglosa a este nivel.
Entonces, ¿han presenciado otros este comportamiento? ¿Alguien tiene una solución mejor que poner SQL sin sentido delante de la instrucción select para cambiar el comportamiento? Siendo que SQL Server debería invocar el orden una vez que se recopilan los datos, parece que este es un error en el servidor que ha persistido durante mucho tiempo. Hemos encontrado que este comportamiento es consistente en muchas de nuestras tablas grandes y es reproducible.
Ediciones:
También debería agregar poner un forceseek
también hace que el problema desaparezca.
Debo agregar para ayudar a los buscadores, el error de tiempo de espera ODBC arrojado es: [Microsoft] [ODBC SQL Server Driver] Operación cancelada
Agregado 10/12/2012: Aún buscando la causa raíz, (junto con haber creado una muestra para dar a Microsoft, publicaré todos los resultados aquí después de enviar). He estado cavando en el archivo de rastreo ODBC entre una consulta de trabajo (con un comentario agregado / declaración de declaración) y una consulta que no funciona. La diferencia fundamental de seguimiento se publica a continuación. Se produce en la llamada a la llamada SQLExtendedFetch después de que todas las discusiones SQLBindCol se hayan completado. La llamada falla con el código de retorno -1, y el subproceso principal luego ingresa SQLCancel. Como podemos producir esto con los controladores ODBC Native Client y Legacy, sigo señalando algunos problemas de compatibilidad en el lado del 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)
Se agregó un caso de Microsoft Connect 10/12/2012:
También debo tener en cuenta que buscamos los planes de consulta tanto para las consultas que funcionan como para las que no funcionan. Ambos se reutilizan adecuadamente según el recuento de ejecuciones. Vaciar los planes en caché y volver a ejecutarlos no cambia el éxito de la consulta.
sp_executesql
y vea qué sucede.
select id, test_date from [big table] where serial_number = ..... order by test_date
? Me pregunto siSELECT *
tiene un impacto negativo en tu rendimiento. Si usted tiene un índice no agrupado entest_date
y un índice agrupado enid
(suponiendo que eso es lo que se llama), esta consulta debe ser cubierta por dicho índice no agrupado y por lo tanto debe regresar con bastante rapidez