サイズ5kの行を更新するときの8k行オーバーフローエラー


8

サイズが5kの行が1つあるターゲットテーブルも、サイズが5kの行に更新しようとしています。

1行なので、行の実際のサイズを簡単に知ることができます。

select *
from sys.dm_db_index_physical_stats(DB_ID('RODS_HSD_ES'), 
OBJECT_ID(N'TBL_BM_HSD_SUBJECT_AN_148_REPRO'), NULL, NULL, 'DETAILED')

再現する

テーブルは作成以来変更されていません。失敗する理由はありません。アイデア?


回答:


9

この問題は、クラスタリングキーを更新しているという事実に関連しており、宛先テーブルにはたまたまパーティション分割スキーマがある1。SQL Serverがクラスタリングキーの任意のコンポーネントを更新するように要求された場合、UPDATEand DELETE、またはハイブリッド更新を実行する必要があり、一部の行はインプレースで更新され、一部は更新されません。

宛先テーブルからクラスター化インデックスを削除すると、更新が機能することがわかります。

エラーメッセージは、少し誤解を招く可能性がありますが、更新中に生成される行サイズが最大長を超えるため、正確です。

テーブルの構造を次のように変更することを検討することをお勧めします。

  • VARCHAR(MAX)それらすべての列には使用しないでください。単一の列に実際に2GBの文字が必要ない場合、なぜそのように列を定義するのですか?現実的に遭遇する最大サイズになるように列を定義します。
  • このテーブルをいくつかのテーブルに分割して、結果の最大行サイズが8060バイト未満になる可能性があります。あなたのような列のいくつかの論理クラスタ、持っているようだV_MAX_xxxV_64_xxxV_512_xxxなどの列を、

再現を簡単にするために、カーソルを削除して、次のDML操作のみを実行することができます。

UPDATE dbo.TBL_BM_HSD_SUBJECT_AN_148_REPRO_TARGET
SET [sampletime]  = '2015-12-29 01:11:26.687';

上記の列は、クラスタリングキーおよびパーティション化キーのコンポーネントの1つです(他のCIキー列の更新は正常に機能します)。

クラスター化インデックスを配置すると、次のエラーが発生します。

メッセージ511、レベル16、状態1、行1

許容最大行サイズ8060より大きいサイズ8287の行は作成できません。

ステートメントは終了されました。

クラスタ化インデックスがない場合、ステートメントは成功します。


1興味深いことに、再現からパーティションを削除すると、クラスター化インデックスが配置されていても、更新が成功することがわかります。


1
私たちはここで解決策への道を進んでいると思います。基本的に、私が変更する必要があるのはsampletimeだけであり、テーブルがパーティション化されているという理由だけで、クラスター化インデックス内にあります。したがって、解決策は、テーブルのパーティション分割の方法を変更することです(これは厄介ですが、可能です)。次に、クラスター化インデックス
Yosi Dahari

10

この更新は、前の質問に答えて説明したのとほぼ同じ理由で失敗します。

あなたがしているので、この場合には、潜在的に複数の行の更新キー列ユニークなインデックスがされて*変更を、SQL Serverは、ソート、割れ目を含む計画を構築し、中間ユニークキー違反を避けるために、演算子を折りたたむ(参照この記事の詳細については) 。

このように導入されたソート演算子は、制限を超える幅の中間行(内部オーバーヘッドを含む)を検出するため、エラーが発生します。OPTION (ROBUST PLAN)更新クエリにヒントを追加すると、これが避けられないことが示されます。

メッセージ8619、レベル16、状態2、行681
ワークテーブルが必要であり、その最小行サイズが最大許容値の8060バイトを超えているため、クエリプロセッサはクエリプランを作成できませんでした。ワークテーブルが必要とされる一般的な理由は、クエリのGROUP BYまたはORDER BY句です。ROBUST PLANヒントなしでクエリを再送信します。

ソースデータとターゲットデータの関係は簡単に見ると不明瞭ですが、各更新操作が最大で1行に影響することが保証できる場合はTOP (1)、更新ステートメントに追加することで、分割/並べ替え/折りたたみの必要性を回避できます。

UPDATE TOP (1) [TBL_BM_HSD_SUBJECT_AN_148_REPRO_TARGET] 
SET ...

ただし、これは少しハックです。理想的には、更新ステートメントの構築とインデックスは、最適化プログラムに十分な情報を提供して、最大で1つの行が更新されることがわかるようにする必要があります。特に、決定論的な更新ステートメントを記述することをお勧めします。

奇妙なデザインと問題の明確さの欠如を考えると、私はデータ関係、またはこれを詳細に達成するために必要となるクエリとインデックスの変更を解読しようとさえしません。

* Martin Smithがコメントで指摘したように、テーブルがパーティション化されていなければ、これはこの特定の状況では問題になりません。更新によってすべての行で同じ決定論的な値にキーが設定される場合、テーブルがそのキーでパーティション化されていない限り、Split / Sort / Collapseは必要ありません。したがって、このクエリの代替ソリューションは、テーブルをsampletimeで分割しないことです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.