Ich versuche, eine Zieltabelle mit einer Zeile der Größe 5k auf eine Zeile der Größe 5k zu aktualisieren.
Da es sich um eine Zeile handelt, ist die tatsächliche Größe der Zeile leicht zu ermitteln:
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')
Die Tabelle wurde seit der Erstellung nicht geändert. Ich sehe keinen Grund, warum es fehlschlagen sollte. Ideen?
sql-server
sql-server-2012
update
Yosi Dahari
quelle
quelle
Antworten:
Das Problem hängt damit zusammen, dass Sie den Clustering-Schlüssel aktualisieren und die Zieltabelle zufällig über ein Partitionierungsschema 1 verfügt . Wenn SQL Server aufgefordert wird, eine Komponente des Clustering-Schlüssels zu aktualisieren, muss ein
UPDATE
undDELETE
oder ein Hybrid-Update durchgeführt werden, bei dem einige der Zeilen direkt aktualisiert werden und andere nicht.Wenn Sie den Clustered-Index aus der Zieltabelle entfernen, funktioniert das Update.
Die Fehlermeldung ist zwar etwas irreführend, aber genau, da die resultierende Zeilengröße während der Aktualisierung die maximale Länge überschreitet.
Ich schlage vor, Sie erwägen, die Struktur der Tabelle zu ändern in:
VARCHAR(MAX)
für alle diese Spalten verwenden. Wenn Sie nicht wirklich 2 GB Zeichen in einer einzelnen Spalte benötigen, warum sollten Sie die Spalte dann so definieren? Definieren Sie die Spalte als die maximale Größe, die realistisch angetroffen wird.V_MAX_xxx
,V_64_xxx
undV_512_xxx
Spalten, usw.Um Ihre Reproduktion zu vereinfachen, möchten Sie möglicherweise den Cursor entfernen und nur die folgende DML-Operation ausführen:
Die obige Spalte ist eine der Komponenten des Clustering-Schlüssels und auch des Partitionierungsschlüssels (das Aktualisieren anderer CI-Schlüsselspalten funktioniert einwandfrei).
Wenn der Clustered-Index vorhanden ist, wird folgende Fehlermeldung angezeigt:
Ohne den Clustered-Index ist die Anweisung erfolgreich.
1 Interessanterweise ist das Update erfolgreich, wenn wir die Partitionierung aus dem Repro entfernen, auch wenn der Clustered-Index vorhanden ist.
quelle
Das Update schlägt aus weitgehend ähnlichen Gründen fehl wie die, die ich in Beantwortung Ihrer vorherigen Frage erläutert habe .
In diesem Fall , weil Sie möglicherweise mehrere Zeilen zu aktualisieren , wo eine Schlüsselspalte eines eindeutigen Index wird * geändert , baut SQL Server einen Plan, der Split enthält, sortieren und Schließen Betreiber Zwischen eindeutigen Schlüssel Verletzungen zu vermeiden (siehe diesen Artikel für weitere Details) .
Der so eingeführte Sortieroperator trifft auf eine Zwischenzeile (einschließlich interner Gemeinkosten) mit einer Breite, die den Grenzwert überschreitet, sodass ein Fehler ausgelöst wird. Das Hinzufügen eines
OPTION (ROBUST PLAN)
Hinweises zur Aktualisierungsabfrage zeigt, dass dies unvermeidbar ist:Die Beziehungen zwischen Quell- und Zieldaten sind mir auf einen kurzen Blick unklar. Wenn Sie jedoch garantieren können , dass jeder Aktualisierungsvorgang höchstens eine Zeile betrifft, können Sie die Notwendigkeit des Aufteilens / Sortierens / Reduzierens vermeiden, indem Sie
TOP (1)
der Aktualisierungsanweisung Folgendes hinzufügen :Dies ist jedoch ein kleiner Hack. Im Idealfall sollten die Konstruktion und die Indizes der Update-Anweisung dem Optimierer genügend Informationen liefern, damit er sehen kann, dass höchstens eine Zeile aktualisiert wird. Insbesondere wird empfohlen, Aktualisierungsanweisungen zu schreiben, die deterministisch sind .
Angesichts des merkwürdigen Designs und der mangelnden Klarheit der Frage werde ich nicht einmal versuchen, die Datenbeziehungen oder Abfrage- und Indexänderungen zu entschlüsseln, die erforderlich wären, um dies im Detail zu erreichen.
* Wie Martin Smith in einem Kommentar betonte, wäre dies in dieser speziellen Situation kein Problem, wenn die Tabelle nicht partitioniert wäre. Wenn das Update den Schlüssel in jeder Zeile auf denselben deterministischen Wert setzt, ist Teilen / Sortieren / Reduzieren nicht erforderlich, es sei denn, die Tabelle ist auch auf diesem Schlüssel partitioniert. Eine alternative Lösung für diese Abfrage besteht darin, die Tabelle nicht zur Abtastzeit zu partitionieren .
quelle