【SQL Server】tempdbのCWT_PrimaryKeyとは
実行プランでCWT_PrimaryKeyというテーブルを参照していることがありますが、どのようなものか気になり調べてみました。
これは静的カーソルの結果セットを保存するtempdbのワークテーブルのようです。
静的カーソルは、カーソルを開いた時点の結果をtempdbへ一旦退避し、後続処理ではそれをFETCHして参照することで、カーソル処理中の処理対象への変更有無に関わらず、開いた時点の情報で処理をすることができます。
このときの静的カーソルの結果セットの格納先がtempdbのCWT_PrimaryKeyとなります。
テスト用データ作成
テスト用にテーブルとレコードを作成します。
CREATE DATABASE Cursor_testDB GO USE Cursor_testDB GO DROP TABLE IF EXISTS dbo.Cursor_test GO CREATE TABLE dbo.Cursor_test( [id] INT ,[column1] VARCHAR(50) ,[column2] VARCHAR(50) ,CONSTRAINT [PK_column] PRIMARY KEY CLUSTERED ([id]) ) GO DECLARE @Id INT ,@Col1 VARCHAR(50) ,@Col2 VARCHAR(50) SET @id = 1 WHILE (@id < 10000) BEGIN SET @Col1 = 'Column' + CONVERT(VARCHAR, @id) SET @Col2 = 'Column' + CONVERT(VARCHAR, 100000-@id) INSERT INTO dbo.Cursor_test(id, column1, column2) VALUES (@id, @Col1, @Col2) SET @id = @id + 1 END GO
作成したテストデータは次のようなものです。
静的カーソルの確認
静的カーソルでクエリを実行してみます。
DECLARE @Id INT ,@Col1 VARCHAR(50) ,@Col2 VARCHAR(50) DECLARE Static_Cursor CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR SELECT id,column1,column2 FROM dbo.Cursor_test WHERE id > 9990 ORDER BY id DESC OPEN Static_Cursor FETCH NEXT FROM Static_Cursor INTO @Id,@Col1,@Col2 WHILE @@FETCH_STATUS = 0 BEGIN PRINT @id PRINT @Col1 PRINT @Col2 FETCH NEXT FROM Static_Cursor INTO @Id,@Col1,@Col2 END CLOSE Static_Cursor DEALLOCATE Static_Cursor GO
実行プランに表示されている内容からtempdbのCWT_PrimaryKeyというワークテーブルに対して読み取り結果を格納し、その後のFETCH処理はtempdbのCWT_PrimaryKeyからクラスター化インデックスを用いて順次取得していることがわかるかと思います。
複数のクエリで静的カーソルを多用すると一度処理対象となる結果セットはtempdbへ格納され、そこから読出しされるため、tempdbへのIO処理が集中しボトルネックとなることがあります。
また、静的カーソルの対象が多い場合はtempdbへ格納する容量もその分増えることになりますのでどちらも注意が必要かと思います。
【参考情報】
静的カーソル
https://technet.microsoft.com/ja-jp/library/ms191286(v=sql.105).aspx
サーバーカーソル動作とクエリパフォーマンスとの関連性について
https://blogs.msdn.microsoft.com/jpsql/2014/04/29/36899/