テンポラリテーブルとテーブル変数の違いを理解しよう
SQL Serverで一時的なデータを扱う場合、テンポラリテーブル(#TempTable/##TempTable)とテーブル変数(@TableVar)のどちらを使うかを正しく判断することが重要です。
どちらもtempdbに作成されますが、スコープ・統計情報・パフォーマンスの性質が異なります。この記事では3種類の特徴を比較し、実務での最適な使い分け方を整理します。
一時オブジェクトの基本概念
一時オブジェクトは、SQL Serverのtempdbに作成される一時的なテーブルです。
クエリ処理中の中間データ保持や一時的な集計に利用されます。代表的な種類は以下の3つです。
- #TempTable:セッション単位で作成されるローカルテンポラリテーブル
- ##TempTable:全セッションで共有可能なグローバルテンポラリテーブル
- @TableVar:変数として宣言されるテーブル型オブジェクト
テンポラリテーブル(#TempTable/##TempTable)の特徴
テンポラリテーブルは通常のテーブルと同様に定義でき、インデックス作成や統計情報の自動生成が行われます。
中〜大規模データを扱う際の中間集計・JOIN処理に適しています。
-- ローカルテンポラリテーブル
CREATE TABLE #SalesTemp (OrderID INT, Amount MONEY);
INSERT INTO #SalesTemp VALUES (1, 5000), (2, 7000);
-- グローバルテンポラリテーブル
CREATE TABLE ##GlobalSalesTemp (OrderID INT, Amount MONEY);
INSERT INTO ##GlobalSalesTemp VALUES (1, 3000);
#TempTableは作成セッションが終了すると自動削除されます。
##TempTableは作成セッション終了後も、他のセッションで参照中は保持されます。
ただし命名衝突リスクがあるため、システム全体で共有する用途に限定するのが安全です。
テーブル変数(@TableVar)の特徴
テーブル変数は「変数」として宣言する一時オブジェクトで、小規模データ向けに軽量に動作します。
統計情報を持たず、クエリオプティマイザが固定推定値(1行)で最適化するため、大量データには不向きです。
DECLARE @SalesVar TABLE (OrderID INT, Amount MONEY);
INSERT INTO @SalesVar VALUES (1, 2000), (2, 3500);
SELECT * FROM @SalesVar;
トランザクションスコープ内でのみ有効で、スコープを抜けると自動的に破棄されます。
関数内や小規模なロジック処理で特に有効です。
各方式の比較(性能・統計情報・スコープ)
| 項目 | #TempTable | ##TempTable | @TableVar |
|---|---|---|---|
| スコープ | セッション単位 | 全セッション共有 | バッチ/関数単位 |
| 統計情報 | 自動生成あり | 自動生成あり | なし |
| インデックス | CREATE INDEX可 | CREATE INDEX可 | 制約経由で可 |
| トランザクション制御 | 対応 | 対応 | 限定的 |
| 削除タイミング | セッション終了時 | 参照終了後 | スコープ終了時 |
| 適用規模 | 中~大規模データ | 共有用途限定 | 小規模データ |
実務での使い分け指針
- 中~大規模データ処理:#TempTable(統計情報とインデックス活用)
- 複数セッションで共有:##TempTable(共有タスク用。命名注意)
- 関数・小規模処理:@TableVar(軽量・高速スコープ限定)
データ件数が多い場合やJOINが多いクエリでは、統計情報の有無がパフォーマンスに大きく影響します。
テンポラリテーブルはオプティマイザに統計情報を提供するため、適切な実行計画を選択できます。
パフォーマンス検証と最適化の例
-- 実行統計の確認
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
-- テンポラリテーブルの使用例
CREATE TABLE #Temp (ID INT PRIMARY KEY, Name NVARCHAR(50));
INSERT INTO #Temp SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), 'Test';
SELECT COUNT(*) FROM #Temp;
-- テーブル変数の使用例
DECLARE @Temp TABLE (ID INT, Name NVARCHAR(50));
INSERT INTO @Temp SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), 'Test';
SELECT COUNT(*) FROM @Temp;
SET STATISTICS IO/TIMEでI/Oと実行時間を比較すると、件数が増えるほど#TempTableの方が有利になります。
テーブル変数で性能が落ちる場合は、OPTION(RECOMPILE)を付けて都度最適化する方法も有効です。
まとめ:ケースに応じた最適な選択を
テンポラリテーブルとテーブル変数は、用途に応じて使い分けることが重要です。
#TempTableは中~大規模処理に最適で、統計情報を活かした高速クエリが可能。
@TableVarは軽量で関数スコープに適し、小規模データや単発処理で有効。
##TempTableは全体共有が必要な特殊ケースで使用します。
システム全体の整合性とパフォーマンスを考慮し、最適な方法を選びましょう。
参考リンク(公式ドキュメント)

0 件のコメント:
コメントを投稿