SQL Server 2008 R2を使用しており、プライマリIDインデックスを持つ非常に大きな(1億行以上)テーブルdatetime
と、非クラスター化インデックスを持つ列があります。私たちは、の使用に基づいていくつかの非常に珍しいクライアント/サーバーの動作を見ているorder by
句を、具体的には、インデックス付きのdatetime列。
私は次の投稿を読みました: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」が使用されない場合にもが呼び出され、その結果も即座に返されるという事実を追加します。
私たちはこの問題をかなり探し回っており、他のユーザーから投稿された同様の問題を目にしていますが、このレベルに分類するものはありません。
他の人がこの動作を目撃したことがありますか?誰かがselectステートメントの前に意味のないSQLを置いて動作を変更するよりも良い解決策を持っていますか?SQL Serverはデータが収集された後に注文を呼び出す必要があるため、これは長い間サーバーに存在するバグのようです。この動作は、大きなテーブルの多くで一貫しており、再現可能であることがわかりました。
編集:
私はまたforceseek
、問題を解消するために追加する必要があります。
サーチャーを助けるために追加する必要があります。スローされるODBCタイムアウトエラーは次のとおりです:[Microsoft] [ODBC SQL Server Driver] Operation cancelled
追加10/12/2012:根本的な原因を突き止める(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)
Microsoft Connectケース10/12/2012を追加しました:
また、機能しているクエリと機能していないクエリの両方のクエリプランを検索したことにも注意してください。どちらも実行回数に基づいて適切に再利用されます。キャッシュされたプランをフラッシュして再実行しても、クエリの成功は変わりません。
sp_executesql
何が起こるかを確認してください。
select id, test_date from [big table] where serial_number = ..... order by test_date
-SELECT *
パフォーマンスに悪影響があるかどうか疑問に思っています。非クラスター化インデックスがオンtest_date
で、クラスター化インデックスがオンになっている場合id
(それがその名前であると想定)、このクエリはその非クラスター化インデックスでカバーされているため、非常に迅速に返されます