2026年3月10日火曜日

SQL Server テンポラリテーブルとテーブル変数の違い|#TempTable・##TempTable・@TableVarの比較

テンポラリテーブルとテーブル変数の違いを理解しよう

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は全体共有が必要な特殊ケースで使用します。
システム全体の整合性とパフォーマンスを考慮し、最適な方法を選びましょう。

SQL Server学習シリーズ

参考リンク(公式ドキュメント)

SQL Server 解説用イメージ

0 件のコメント:

コメントを投稿