[解決済み】SQL Serverでtempテーブルとテーブル変数の違いは何ですか?
質問
SQL Server 2005では、2つの方法でtempテーブルを作成することができます。
declare @tmp table (Col1 int, Col2 int);
または
create table #tmp (Col1 int, Col2 int);
この2つの違いは何でしょうか? 私は、@tmpがまだtempdbを使用しているのか、それともすべてがメモリ上で起こるのかについて、相反する意見を読んだことがあります。
どのようなシナリオで、一方が他方より優れているのでしょうか?
どのように解決するのか?
Temporary Tables (#tmp) と Table Variables (@tmp) にはいくつかの違いがありますが、以下の MSDN のリンクにあるように tempdb の使用はそのうちのひとつではありません。
経験則上、少量から中量のデータと単純な使用シナリオの場合は、テーブル変数を使用する必要があります。(これは大雑把なガイドラインで、もちろん例外もたくさんあります。下記と以下の記事を参照してください)
両者を選択する際のポイントをいくつか紹介します。
-
テンポラリーテーブルは実際のテーブルなので、CREATE INDEXなどの操作を行うことができます。もし、大量のデータがあり、インデックスでアクセスした方が速い場合は、テンポラリテーブルが良い選択肢となります。
-
テーブル変数は、PRIMARY KEY制約またはUNIQUE制約を使用してインデックスを持つことができます。(一意でないインデックスが必要な場合は、一意制約の最後の列として主キー列を含めるだけです。一意なカラムがない場合は、ID カラムを使用することができます)。 SQL 2014には非ユニークインデックスもある .
-
テーブル変数はトランザクションに参加しないし
SELECT
は暗黙のうちにNOLOCK
. 例えば、プロシージャの途中でロールバックする場合、そのトランザクション中に投入されたテーブル変数がそのまま投入されます!トランザクションの動作は非常に便利です。 -
Tempテーブルは、ストアドプロシージャを再コンパイルすることになるかもしれません(おそらく頻繁に)。テーブル変数はそうではありません。
-
SELECT INTOを使用して一時テーブルを作成することができます。これは、素早く書くことができ(アドホックなクエリに適しています)、一時テーブル構造を前もって定義する必要がないため、時間と共に変化するデータ型に対処することができるかもしれません。
-
関数からテーブル変数を渡すことができるので、ロジックのカプセル化と再利用がより簡単になります (例えば、文字列を任意の区切り文字で値のテーブルに分割する関数を作成します)。
-
ユーザ定義関数内でテーブル変数を使用すると、その関数をより広く使用することができます(詳細はCREATE FUNCTIONドキュメントを参照してください)。もし関数を書くのであれば、他にやむを得ない理由がない限り、一時テーブルよりもテーブル変数を使用すべきです。
-
テーブル変数もテンポラリテーブルもtempdbに保存されます。しかし、(2005年以降の)テーブル変数のデフォルトは現在のデータベースの照合順序であり、tempdbのデフォルトの照合順序を取るtempテーブルとは異なります ( レフ ). つまり、tempテーブルを使用していて、データベースの照合順序がtempdbと異なる場合、tempテーブルのデータとデータベースのデータを比較する場合に問題が発生するため、照合順序の問題に注意する必要があります。
-
グローバルテンポテーブル (##tmp) は、すべてのセッションとユーザーが利用できる別のタイプのテンポラリテーブルです。
さらにいくつかの読み物があります。
-
マーティン・スミスの大正解 dba.stackexchange.comにあります。
-
MSDN FAQで両者の違いについて解説しています。 https://support.microsoft.com/en-gb/kb/305977
-
MDSNブログの記事です。 https://docs.microsoft.com/archive/blogs/sqlserverstorageengine/tempdb-table-variable-vs-local-temporary-table
-
記事 https://searchsqlserver.techtarget.com/tip/Temporary-tables-in-SQL-Server-vs-table-variables
-
テンポラリテーブルとテンポラリ変数の予期せぬ動作とパフォーマンスへの影響。 SQLblog.comのPaul White
関連
-
[解決済み] SQL Server テーブルにカラムが存在するかどうかを確認する方法は?
-
[解決済み] SQL Server の DateTime データ型から日付だけを返す方法
-
[解決済み] varcharとnvarcharの違いは何ですか?
-
[解決済み] SQL Server にテーブルが存在するかどうかを確認する
-
[解決済み] JOINとINNER JOINの違いについて
-
[解決済み] SQL ServerでJOINを使用してテーブルを更新しますか?
-
[解決済み] SQL Serverにおけるchar、nchar、varchar、nvarcharの違いは何ですか?
-
[解決済み] T-SQLでテーブル変数をSELECT INTOする
-
[解決済み】SQL Serverで既存のテーブルにデフォルト値を持つカラムを追加する
-
[解決済み】SQLサーバーでテーブル変数と一時テーブルを使用するのはいつですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] SQL Server Error "String Data, Right Truncation "の意味と修正方法について教えてください。
-
[解決済み] 各GROUP BY式は、外部参照でない列を少なくとも1つ含む必要があります。
-
[解決済み] SSRS レポートの定義が無効です。
-
[解決済み] ')' 付近の構文が正しくない場合の対処方法
-
[解決済み] SQL Agent を使用して SSIS パッケージを実行する際の問題 - "DTSER_FAILURE(1)" で失敗します。
-
[解決済み] SSISで新しいレコードを挿入する前に、宛先テーブルを空にするにはどうすればよいですか?
-
[解決済み] SSRS 2つ目の文字列の前にある文字列から部分文字列を抽出する
-
[解決済み] SQL ServerでBegin / End BlocksとGoキーワードを使用する?
-
[解決済み】SQLサーバーでテーブル変数と一時テーブルを使用するのはいつですか?
-
[解決済み】テーブル変数にインデックスを作成する