tsql-bulk-update
MyTableA hat mehrere Millionen Datensätze. In regelmäßigen Abständen wird jede Zeile MyTableA muss aktualisiert werden, mit Werten von TheirTableA.
Leider habe ich keine Kontrolle über TheirTableA und es gibt kein Feld, um anzugeben, ob alles in TheirTableA geändert hat, so dass ich entweder alles neu machen oder ich ein update basierend auf dem Vergleich jedes Feld, das unterschiedlich sein könnte (nicht wirklich machbar, da dies eine lange und Breite Tabelle).
Leider das Transaktionsprotokoll ist eine Ballonfahrt dabei eine gerade update also wollte ich aufteilen, es mit UPDATE TOP, aber wie ich es verstehe, brauche ich ein paar Felder, um zu bestimmen, ob die Datensätze in MyTableA aktualisiert wurden oder noch nicht, sonst werde ich am Ende in einer Endlosschleife:
declare @again as bit;
set @again = 1;
while @again = 1
begin
update top (10000) MyTableA
set my.A1 = their.A1, my.A2 = their.A2, my.A3 = their.A3
from MyTableA my
join TheirTableA their on my.Id = their.Id
if @@ROWCOUNT > 0
set @again = 1
else
set @again = 0
end
ist der einzige Weg, dies funktioniert, wenn ich in ein
where my.A1 <> their.A1 and my.A2 <> their.A2 and my.A3 <> their.A3
dieser scheint, wie es wird schrecklich ineffizient, mit vielen Spalten zu vergleichen
Ich bin sicher, ich bin fehlt eine offensichtliche alternative?
- "Leider wird das Transaktionsprotokoll Ballonfahren zu tun" - haben Sie regelmäßig Log-sicherungen? Wie oft?
- Eine offensichtliche Sache, die ich bin fehlt, ist kleben ein updatedAt datetime-Feld auf MyTable, diese mit einem index ist, angemessene Leistung, aber ich würde immer noch interessieren, ob es einen besseren Weg gibt?
- Gerade über diese Frage von vor 2 Jahren. Sorry, ich wollte nicht akzeptieren, dann Antworten und ich erinnere mich nicht das genaue Ergebnis jedoch von Ihnen positiv bewertet werden und angenommen, wo Sie angeboten habe nützliche info für andere user 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nun der erste, und einfachste Lösung wäre natürlich, wenn Sie sich ändern könnte, das schema um einen Zeitstempel für den letzten update - und dann nur aktualisieren Sie die Zeilen mit einem Zeitstempel neuer als die Letzte änderung.
Aber wenn das nicht möglich ist, einen anderen Weg zu gehen, könnte sein, die HashBytes Funktion, vielleicht durch die Verkettung der Felder in eine xml, die du dann vergleichen. Der Nachteil hier ist eine 8kb-Grenze (https://connect.microsoft.com/SQLServer/feedback/details/273429/hashbytes-function-should-support-large-data-types) EDIT: ich habe Mal wieder gestohlen code, dieses mal aus:
http://sqlblogcasts.com/blogs/tonyrogerson/archive/2009/10/21/detecting-changed-rows-in-a-trigger-using-hashbytes-and-without-eventdata-and-or-s.aspx
Beispielsweise sein:
Letztes Mittel (und meine ursprüngliche Vorschlag) ist, zu versuchen, Binary_Checksum? Wie bereits im Kommentar, bedeutet dies nicht, öffnen Sie das Risiko ein eher hohes kollisionsrisiko.
http://msdn.microsoft.com/en-us/library/ms173784.aspx
Ich habe gestohlen das folgende Beispiel aus lessthandot.com - link zu den vollständigen SQL (und andere Coole Funktionen) ist unten.
Beispiel von http://wiki.lessthandot.com/index.php/Ten_SQL_Server_Functions_That_You_Have_Ignored_Until_Now
Vorausgesetzt, beide Tabellen haben die gleiche Struktur, können Sie eine Ergebnismenge von Zeilen, die anders sind, mit
SELECT * into #different_rows from MyTable EXCEPT select * from TheirTable
und aktualisieren Sie dann aus, die mit einem beliebigen Schlüssel-Felder sind verfügbar.Ich weiß nicht, ob dies besser ist, als das hinzufügen
where my.A1 <> their.A1 and my.A2 <> their.A2 and my.A3 <> their.A3
, aber ich würde auf jeden Fall geben, es zu versuchen (vorausgesetzt, SQL Server 2005+):Ist, deklarieren Sie eine table-variable für die Erfassung der IDs der Zeilen aktualisiert werden, und verwenden Sie diese Tabelle zum nachschlagen (und das weglassen) - IDs, die bereits aktualisiert wurden.
Einer leichten variation auf die Methode wäre, um eine lokale temporäre Tabelle anstelle einer Tabelle variable. Auf diese Weise würde man in der Lage sein, erstellen Sie einen index auf der ID-lookup-Tabelle, die möglicherweise zu einer verbesserten Leistung führen.
Wenn die schema-änderung ist nicht möglich. Wie über die Verwendung von trigger zu speichern off die Ids sich geändert haben. Und nur den import/export die Zeilen.
Oder verwenden Sie trigger exportieren Sie es sofort.