列をINTからBIGINTに変更して実行していたところ、テーブルサイズは250 GBで、1時間後にtempdbがいっぱいになったためバージョンストアエラーが発生しました。
私の知る限り、メモリページとログファイルのみが必要ですが、Tempdbについてはわかりません。誰かがこの内部を説明できますか?
コミットされた読み取り分離を使用しています。
select
name,
snapshot_isolation_state_desc,
is_read_committed_snapshot_on
from sys.databases
...このデータベースの場合:
名前:データベース名 スナップショット_アイソレーション_状態_desc:オフ is_read_committed_snapshot_on:0
単純なALTER TABLE
について話していると仮定します。一時テーブルを実行してトリックや名前を変更するウィザードなどを使用して実行される操作ではありません。
ストレートカラムのデータタイプの変更mayにより、every行が更新されますテーブル。関係するタイプによって異なります。これを考慮する必要があります。テーブルの行イメージは、エンジンによって何らかの方法で解釈されるまで、バイトのバッグです。エンジンは、テーブルメタデータの説明に従って、これらのバイトが何であるかを理解します。メタデータには、「オフセット12からオフセット16までは整数、列番号4です。オフセット17からオフセット19まではショート、列番号5など」と続きます。これで、列タイプを変更するALTERを実行すると、メタデータが変更されます。そして今$ 1Mの質問:新しいメタデータは同じバイトのバッグを正しく記述しますか?はいの場合、行ALTERは瞬間的であり、テーブル内のすべての行は変更されません。そうでない場合は、all行を更新する必要があります。巨大なテーブルは、すべて1つのトランザクションで巨大な更新につながります。この更新により、リソースが使い果たされる可能性があります(ログスペースが不足するなど)。 Shankyは、この「更新」が一時テーブル->挿入の形式を取る可能性があることは正しいですが、これは実装の詳細です。
先ほど書いた 内部のSQL Serverテーブル列 は、これらの操作の一部がどのように発生し、実際の物理行セットメタデータに証拠が残されるかを示しています。
さて、この操作が完了すると、スナップショットが有効になっていない場合でも、バージョンストア領域が不足していると言いますよね?バージョンストアは、スナップショットアイソレーション以外にも使用されます。よく知られている例を挙げると、トリガーのDELETED疑似テーブルは、バージョンストアから提供されます。つまり、スナップショット分離を有効にしていない場合でも、バージョンストアを使用できます。 SQL ServerでのTempDBの管理:TempDBの基本(バージョンストア:なぜ必要なのか?) を参照してください。Sunilは、スナップショットに関連しない3つのバージョンストアの使用法(トリガー、MARS、オンラインインデックスビルド)を引用しています。
SQL 2014はオンラインの列の変更をサポートしていません。DDL操作として、トリガーやMARSの行のバージョン管理は必要ありません。だから私見それはバージョンストアを拡大すべきではありません。
私の主な容疑者は、この場合、読み取り可能な二次的なものです(ここでは暗闇の中でのショットです...)。読み取り可能なセカンダリがすべての読み取りをスナップショット分離にマップするという事実は 十分に文書化されています です。詳細を正確に覚えていないので間違っているかもしれませんが、セカンダリデータベースがスナップショット分離をサポートするには、プライマリがバージョンストアを使用する必要があると思います。セカンダリがプライマリの物理的なコピーであり、行サイズが一致している必要があるという事実について考えてください。
おそらく回答ではありませんが、コメントするには長すぎます。
私は、dbエンジンが新しい一時テーブルを作成し、それを埋めていると思います。実行計画を確認すると、手掛かりが得られる場合があります。次の記事で引用を見ることができますが、検索した後、MSのドキュメントで公式なものは何も見つかりませんでした。
また、SSMSデザイナーを使用してこれを実行している場合、テーブルの変更クエリを実行する場合とは異なる動作をする可能性があります。保存をクリックする代わりにデザイナーを使用する場合は、代わりにクエリをスクリプト化できます。
SSMSを使用して実行された場合のほとんどのALTER TABLE操作は、テーブルの削除と再作成を引き起こします
必要に応じて、自分で新しいテーブルを作成し、データを新しいテーブルにポンプできるように調整します。プロセス中に書き込みのためにそのテーブルを開いたままにする必要がある場合は、さらに複雑になります。
また、操作の実行中にTempDBに一時的に500GBを追加することもできます。 250GBのテーブルではそれ以上は必要ありませんが、TempDBで見慣れないものを見てきました。
段落を引用しています
付録A:Management Studioを使用してデータタイプを変更するSQL Server 2005ドキュメントの 照合順序とデータタイプの変更の影響
列のデータ型を変更すると、次のことが起こります
内部的に、SQL Serverは、ターゲット列と同じ列プロパティを持つ一時テーブルを作成します。
次に、INSERT INTOステートメントが実行され、データが一時テーブルにコピーされます。
彼らがプロファイラーを使用したとき、次のクエリが見られました。
IF EXISTS(SELECT * FROM dbo.t1)--T1 was table with col C1 whose data type was changed
EXEC('INSERT INTO dbo.Tmp_t1 (c1)
SELECT CONVERT(nchar(10), c1) FROM dbo.t1 WITH (HOLDLOCK TABLOCKX)')
- その後、元のテーブルにインデックスが存在し、テーブル名が元のテーブル名に変更された場合、インデックスが追加されます。
非常に大きなテーブルがあるため、一時テーブルも大きく、Tempdbがそれを収容できず、テーブルがいっぱいになったとしましょう。