우리는 SQL Server 2008 R2를 사용하고 있으며 기본 id 인덱스가있는 매우 큰 (100M + 행) 테이블과 datetime
비 클러스터형 인덱스가 있는 열을 가지고 있습니다. 우리는의 사용에 따라 일부 매우 이례적인 클라이언트 / 서버 동작을보고있는 order by
절 특히 A의 인덱스 날짜 열을 .
다음 게시물을 읽었습니다 .https : //stackoverflow.com/questions/1716798/sql-server-2008-ordering-by-datetime-is-too-slow 그러나 클라이언트 / 서버에 대한 것보다 더 많은 일이 있습니다. 여기에 설명을 시작하십시오.
다음 쿼리를 실행하면 (일부 내용을 보호하도록 편집 됨) :
select *
from [big table]
where serial_number = [some number]
order by test_date desc
쿼리는 매번 시간 초과됩니다. SQL Server 프로파일 러에서 실행 된 쿼리는 다음과 같습니다.
exec sp_cursorprepexec @p1 output,@p2 output,NULL,N'select * .....
이제 검색어를 수정하면 다음과 같이 말합니다.
declare @temp int;
select * from [big table]
where serial_number = [some number]
order by test_date desc
SQL Server 프로파일 러는 실행 된 쿼리가 서버에 다음과 같이 표시되며 즉시 작동합니다.
exec sp_prepexec @p1 output, NULL, N'declare @temp int;select * from .....
사실, 사용하지 않는 선언문 대신 빈 주석 ( '-;')을 넣고 동일한 결과를 얻을 수도 있습니다. 그래서 처음에 우리는이 문제의 근본 원인으로 sp 전처리기를 가리 켰지 만, 이렇게하면 :
select *
from [big table]
where serial_number = [some number]
order by Cast(test_date as smalldatetime) desc
즉시 작동합니다 (다른 datetime
유형 으로 캐스팅 할 수 있음 ). 밀리 초 단위로 결과를 반환합니다. 그리고 프로파일 러는 서버에 대한 요청을 다음과 같이 표시합니다.
exec sp_cursorprepexec @p1 output, @p2 output, NULL, N'select * from .....
따라서 sp_cursorprepexec
문제의 전체 원인에서 절차 가 다소 제외됩니다 . 여기에 sp_cursorprepexec
'order by'가 사용되지 않을 때도 호출되고 결과도 즉시 반환 된다는 사실을 추가하십시오 .
우리는이 문제에 대해 google을 약간 살펴 보았지만 다른 사람들이 비슷한 문제를 게시했지만이 수준으로 분류하는 것은 없습니다.
다른 사람들이이 행동을 목격 했습니까? 누구든지 select 문 앞에 의미없는 SQL을 배치하여 동작을 변경하는 것보다 더 나은 솔루션을 가지고 있습니까? SQL Server가 데이터를 수집 한 후 주문을 호출해야하므로 서버에서 오랫동안 지속 된 버그 인 것 같습니다. 우리는이 동작이 우리의 많은 큰 테이블에서 일관성이 있고 재현 가능한 것을 발견했습니다.
편집 :
또한 퍼팅 추가해야합니다 forceseek
또한 문제가 사라질 수있다.
검색자를 돕기 위해 추가해야하는 ODBC 시간 초과 오류는 다음과 같습니다. [Microsoft] [ODBC SQL Server 드라이버] 작업이 취소되었습니다.
2012 년 10 월 12 일 추가 : 여전히 근본 원인을 찾아냅니다 (Microsoft에 제공하기 위해 샘플을 작성 한 것과 함께 제출 한 후 여기에 결과를 게시 할 것입니다). 작업 쿼리 (추가 주석 / 선언문 포함)와 작동하지 않는 쿼리 사이의 ODBC 추적 파일을 파고 들었습니다. 기본적인 미량 차이는 다음과 같습니다. 모든 SQLBindCol 토론이 완료된 후 SQLExtendedFetch 호출에 대한 호출에서 발생합니다. 리턴 코드 -1로 호출이 실패한 후 상위 스레드가 SQLCancel을 입력합니다. 우리는 Native Client 및 Legacy ODBC 드라이버를 사용하여 이것을 생성 할 수 있기 때문에 여전히 서버 측에서 일부 호환성 문제를 지적하고 있습니다.
(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)
2012 년 10 월 12 일 Microsoft Connect 사례가 추가되었습니다.
또한 작동하는 쿼리와 작동하지 않는 쿼리 모두에 대한 쿼리 계획을 찾았습니다. 이들은 모두 실행 횟수에 따라 적절하게 재사용됩니다. 캐시 된 계획을 비우고 다시 실행해도 쿼리 성공은 바뀌지 않습니다.
sp_executesql
어떤 일이 발생하는지 보십시오 .
select id, test_date from [big table] where serial_number = ..... order by test_date
-SELECT *
성능에 부정적인 영향이 있는지 궁금합니다 . 당신이 클러스터되지 않은 인덱스가있는 경우test_date
와에 클러스터 된 인덱스id
(그것이라고 그 무엇의 가정을),이 쿼리는해야 덮여 그 클러스터되지 않은 인덱스 때문에 매우 빨리 반환해야합니다