Bulk-Operationen performant umsetzen: Batching, Locking, Constraints
AI generated
SELECT
JOIN
SQL · Datenbank-Performance · Batch-Processing
Bulk-Operationen performant umsetzen
von der Zeilen-Schleife zum kontrollierten Batch

Wer grosse Datenmengen per Zeile fuer Zeile einfuegt, aktualisiert oder loescht, produziert Lock-Eskalation, aufgeblaehte Transaktionslogs und Laufzeiten im Stundenbereich. Mit durchdachtem Batching, temporaer deaktivierten Indizes und richtig dimensionierten Chunks werden dieselben Bulk-Operationen zu einer Aufgabe von Minuten, ohne den laufenden Betrieb der Datenbank zu blockieren.

18 Min. Lesezeit Bulk Insert · Bulk Update · Bulk Delete · Chunking MySQL · PostgreSQL · SQL Server

1. Warum Row-by-Row bei Bulk-Operationen scheitert

Eine Bulk-Operation ist jede INSERT-, UPDATE- oder DELETE-Anweisung, die nicht eine einzelne Zeile, sondern tausende bis Millionen Zeilen in einem Rutsch verarbeitet. Der naive Ansatz, jede Zeile in einer eigenen Transaktion mit einem eigenen Roundtrip zur Datenbank zu verarbeiten, funktioniert bei hundert Zeilen problemlos und bricht bei einer Million Zeilen komplett zusammen. Jede einzelne Anweisung kostet Netzwerk-Latenz, Parsing, Log-Flush und Lock-Verwaltung, und diese Kosten summieren sich linear mit der Zeilenzahl statt sich zu amortisieren.

Das eigentliche Problem liegt aber tiefer als reine Geschwindigkeit. Row-by-Row-Verarbeitung haelt Transaktionen unnoetig lange offen, was Locks laenger blockiert als noetig und in vielen Datenbanksystemen zu Lock-Eskalation fuehrt, bei der aus vielen Row-Locks ein blockierender Table-Lock wird. Parallele Lese- und Schreibzugriffe anderer Sessions werden dadurch ausgebremst oder komplett blockiert, waehrend die eigentliche Bulk-Operation laeuft. Wer Bulk-Operationen richtig dimensioniert, vermeidet genau dieses Szenario und haelt den produktiven Betrieb der Datenbank waehrend der Verarbeitung grosser Datenmengen aufrecht.

Die folgenden Abschnitte behandeln Bulk-Operationen fuer INSERT, UPDATE und DELETE getrennt, weil jede Operation unterschiedliche Engpaesse hat. Anschliessend geht es um Index-Handling, Transaktionsgroesse, Locking und Monitoring, die Aspekte, die jede Art von Massenverarbeitung betreffen und ueber Erfolg oder Ausfall eines Wartungsfensters entscheiden.

2. Bulk Insert: Batching statt Einzel-Insert

Der wichtigste Hebel bei Bulk-Insert-Operationen ist, mehrere Zeilen in einer einzigen Anweisung zu uebergeben, statt fuer jede Zeile eine eigene INSERT-Anweisung zu senden. Die Multi-Row-VALUES-Syntax reduziert Parsing-Overhead und Netzwerk-Roundtrips drastisch, weil die Datenbank den Ausfuehrungsplan einmal statt tausendfach aufstellt. In der Praxis liegt der Geschwindigkeitsgewinn bei Batches von 500 bis 1000 Zeilen pro Anweisung oft bei einer Groessenordnung gegenueber Einzel-Inserts, mit abnehmendem Grenznutzen bei noch groesseren Batches.

Fuer wirklich grosse Datenmengen, etwa beim initialen Laden einer Tabelle aus einer CSV-Datei, sind spezialisierte Bulk-Load-Mechanismen die schnellste Option. MySQL bietet LOAD DATA INFILE, PostgreSQL COPY, SQL Server BULK INSERT. Diese Mechanismen umgehen einen Grossteil des SQL-Parsers und schreiben Daten deutlich naeher am Storage-Layer, was bei mehreren Millionen Zeilen den Unterschied zwischen Minuten und Stunden ausmacht. Wo diese Werkzeuge verfuegbar sind, sollten sie gegenueber generischem INSERT-Batching bevorzugt werden.

Ein oft uebersehener Aspekt bei Bulk-Insert-Operationen ist das Verhalten von Auto-Increment-Spalten und Triggern. Jeder aktive Trigger wird pro Zeile ausgefuehrt, auch bei einem Multi-Row-INSERT, und kann den Geschwindigkeitsvorteil des Batchings komplett zunichtemachen. Vor einem grossen Bulk-Load lohnt sich daher immer ein Blick auf aktive Trigger und Foreign-Key-Constraints auf der Zieltabelle, weil beide pro Zeile geprueft werden und bei Millionen Zeilen spuerbar Zeit kosten.


-- Bulk-Operationen: multi-row INSERT instead of one statement per row
-- Slow: one round trip per row (avoid for large data sets)
-- INSERT INTO orders (customer_id, total, status) VALUES (101, 49.90, 'open');
-- INSERT INTO orders (customer_id, total, status) VALUES (102, 12.50, 'open');

-- Fast: batched multi-row INSERT, one round trip per batch
INSERT INTO orders (customer_id, total, status) VALUES
  (101, 49.90, 'open'),
  (102, 12.50, 'open'),
  (103, 87.30, 'open'),
  (104, 5.99,  'open');
  -- continue up to a few hundred rows per statement, then start a new batch

-- PostgreSQL: fastest option for initial bulk loads
COPY orders (customer_id, total, status)
FROM '/data/orders_export.csv'
WITH (FORMAT csv, HEADER true);

-- MySQL equivalent
LOAD DATA INFILE '/data/orders_export.csv'
INTO TABLE orders
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;

3. Bulk Update: satzbasiert statt Cursor-Schleife

Ein haeufiger Anti-Pattern bei Bulk-Update-Aufgaben ist ein Cursor, der jede Zeile einzeln durchgeht und pro Zeile ein separates UPDATE ausfuehrt. Relationale Datenbanken sind fuer satzbasierte Operationen optimiert, nicht fuer prozedurale Zeilen-fuer-Zeile-Verarbeitung. Ein einziges UPDATE mit einer WHERE-Klausel, das alle betroffenen Zeilen in einem Durchlauf aendert, nutzt Indizes und den Optimizer viel effizienter als eine Schleife mit tausenden Einzelanweisungen und ist in aller Regel um ein Vielfaches schneller.

Bei Bulk-Update-Operationen, die Werte aus einer anderen Tabelle uebernehmen, ist ein UPDATE mit JOIN die richtige Wahl. MySQL und SQL Server erlauben direkte JOIN-Syntax im UPDATE, PostgreSQL nutzt dafuer die FROM-Klausel. Der entscheidende Vorteil gegenueber einer Schleife mit Einzel-Lookups: Der Optimizer sieht die gesamte Operation als eine Einheit und kann den effizientesten Join-Algorithmus fuer die komplette Datenmenge waehlen, statt fuer jede Zeile einzeln einen Index-Lookup durchzufuehren.


-- Bulk-Operationen: set-based UPDATE instead of row-by-row cursor loop

-- MySQL / SQL Server style: UPDATE with JOIN
UPDATE orders o
JOIN customers c ON c.id = o.customer_id
SET o.customer_tier = c.tier
WHERE o.updated_at IS NULL;

-- PostgreSQL style: UPDATE with FROM
UPDATE orders o
SET customer_tier = c.tier
FROM customers c
WHERE c.id = o.customer_id
  AND o.updated_at IS NULL;

-- Anti-pattern: avoid this for large row counts
-- FOR row IN (SELECT id FROM orders WHERE updated_at IS NULL) LOOP
--   UPDATE orders SET customer_tier = ... WHERE id = row.id;
-- END LOOP;

4. Bulk Delete: Chunking gegen Lock-Eskalation

Ein einzelnes DELETE, das mehrere Millionen Zeilen in einer Transaktion entfernt, ist der klassische Ausloeser fuer Lock-Eskalation und ein explodierendes Transaktionslog. Die Datenbank muss jede geloeschte Zeile bis zum Commit vorhalten, um Rollback zu ermoeglichen, was bei grossen Mengen den Undo-Bereich oder das Write-Ahead-Log erheblich aufblaeht und im Extremfall zu Speicherplatzproblemen fuehrt. Das richtige Bulk-Operationen-Pattern fuer DELETE ist Chunking: Die Loeschung wird in kleine, wiederholte Transaktionen von einigen tausend Zeilen aufgeteilt, jede mit eigenem Commit.

Chunking hat einen weiteren praktischen Vorteil: Zwischen den einzelnen Chunks kann kurz gewartet werden, damit andere Sessions ihre Locks bekommen und replizierte Systeme nicht in Verzug geraten. Bei Datenbanken mit Replikation, etwa MySQL mit Row-Based-Replication, erzeugt ein einzelnes riesiges DELETE einen ebenso riesigen Batch von Replikationsereignissen, der die Replikations-Verzoegerung auf Sekunden oder Minuten hochtreibt. Kleine, gestaffelte Chunks halten diese Verzoegerung nahe null.

Bei sehr grossen Loeschungen, etwa dem Bereinigen einer Log-Tabelle mit Milliarden Zeilen, ist Partitionierung dem klassischen DELETE oft ueberlegen. Statt Zeilen einzeln zu loeschen, wird eine ganze Partition mit einem DDL-Befehl entfernt, was praktisch sofort geschieht und kein Transaktionslog im gleichen Umfang erzeugt. Diese Strategie erfordert allerdings, dass die Tabelle von Anfang an partitioniert angelegt wurde, etwa nach Datum.


-- Bulk-Operationen: chunked DELETE to avoid lock escalation and log bloat

-- MySQL / PostgreSQL: delete in chunks of 5000 rows, loop until no rows left
DELETE FROM audit_log
WHERE created_at < '2024-01-01'
LIMIT 5000;
-- Repeat this statement (application loop or scheduled job)
-- until ROW_COUNT() returns 0. Commit after each chunk.

-- PostgreSQL: LIMIT is not valid directly on DELETE, use a subquery
DELETE FROM audit_log
WHERE ctid IN (
  SELECT ctid FROM audit_log
  WHERE created_at < '2024-01-01'
  LIMIT 5000
);

-- SQL Server: TOP instead of LIMIT
DELETE TOP (5000) FROM audit_log
WHERE created_at < '2024-01-01';

-- Partition drop: near-instant bulk delete for partitioned tables
ALTER TABLE audit_log DROP PARTITION p_2023;

5. Indizes und Constraints temporaer deaktivieren

Jeder Index auf einer Zieltabelle wird bei jedem INSERT und UPDATE mitgepflegt, und bei einem grossen Bulk-Load kann dieser Wartungsaufwand die eigentliche Datenoperation deutlich uebersteigen. Fuer initiale Massenladungen, etwa eine Migration mit mehreren Millionen Zeilen in eine leere oder fast leere Tabelle, ist es oft schneller, sekundaere Indizes vor dem Laden zu entfernen und danach in einem Zug neu aufzubauen, statt sie waehrend jeder einzelnen Zeile inkrementell zu pflegen. Ein Index-Neuaufbau auf sortierten Daten ist deutlich effizienter als tausende einzelne Index-Insertionen.

Foreign-Key-Constraints funktionieren aehnlich: Jede Zeile wird gegen die referenzierte Tabelle geprueft, was bei grossen Bulk-Operationen spuerbare Zeit kostet. MySQL erlaubt, Fremdschluessel-Pruefungen fuer eine Session mit SET FOREIGN_KEY_CHECKS=0 temporaer abzuschalten, PostgreSQL bietet ALTER TABLE ... DISABLE TRIGGER ALL fuer denselben Zweck. Wichtig dabei: Diese Abkuerzung ist nur vertretbar, wenn die Datenintegritaet durch die Quelle der Daten bereits garantiert ist, etwa bei einer Migration aus einem konsistenten System, und die Constraints nach dem Laden zwingend wieder aktiviert und idealerweise validiert werden.

Bei laufenden Systemen, die waehrend der Bulk-Operation weiter bedient werden muessen, ist das komplette Abschalten von Constraints riskant, weil in der Zwischenzeit inkonsistente Daten entstehen koennen. Hier ist der sicherere Weg, Indizes zu behalten, aber die Batch-Groesse so zu waehlen, dass der Index-Wartungsaufwand pro Batch klein bleibt, statt die Sicherheitsnetze komplett zu entfernen.


-- Bulk-Operationen: temporarily disable indexes and constraints for large loads

-- MySQL: disable secondary index maintenance during load (MyISAM/InnoDB differ)
ALTER TABLE products DISABLE KEYS;
-- ... run the bulk load ...
ALTER TABLE products ENABLE KEYS;

-- MySQL: skip foreign key checks for a trusted, consistent data source
SET FOREIGN_KEY_CHECKS = 0;
-- ... run the bulk load ...
SET FOREIGN_KEY_CHECKS = 1;

-- PostgreSQL: drop and recreate an index instead of incremental maintenance
DROP INDEX IF EXISTS idx_products_sku;
-- ... run the bulk load ...
CREATE INDEX CONCURRENTLY idx_products_sku ON products (sku);

-- PostgreSQL: disable triggers (includes FK checks) for a session
ALTER TABLE order_items DISABLE TRIGGER ALL;
-- ... run the bulk load ...
ALTER TABLE order_items ENABLE TRIGGER ALL;

6. Transaktionsgroesse und Commit-Intervalle

Die Wahl der Transaktionsgroesse ist bei Bulk-Operationen ein direkter Kompromiss zwischen Durchsatz und Ressourcenverbrauch. Eine einzige riesige Transaktion minimiert Commit-Overhead, haelt aber Locks lange offen und laesst das Transaktionslog stark anwachsen. Viele kleine Transaktionen halten Locks kurz und das Log schlank, kosten aber pro Commit einen Log-Flush zur Festplatte, was bei zu kleinen Batches den Durchsatz wieder senkt. Die Praxis zeigt, dass Batch-Groessen zwischen 1000 und 10000 Zeilen fuer die meisten Workloads ein gutes Gleichgewicht bieten.

Ein wichtiger Nebeneffekt kleinerer Batches: Wenn ein Fehler mitten in der Verarbeitung auftritt, etwa eine Constraint-Verletzung bei Zeile 3 Millionen, muss bei einer einzigen grossen Transaktion der komplette Rollback aller bereits verarbeiteten Zeilen erfolgen, was bei Millionen Zeilen selbst Minuten dauern kann. Bei gechunkten Bulk-Operationen mit Commit nach jedem Batch geht bei einem Fehler nur der aktuelle, kleine Batch verloren, und die Verarbeitung kann ab dem letzten erfolgreichen Punkt fortgesetzt werden.


-- Bulk-Operationen: explicit batch loop with progress tracking

-- Progress table: resume from the last successfully committed key
CREATE TABLE bulk_job_progress (
  job_name VARCHAR(100) PRIMARY KEY,
  last_processed_id BIGINT NOT NULL DEFAULT 0,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- One batch: process 2000 rows, commit, then update progress
START TRANSACTION;

UPDATE customers
SET loyalty_tier = 'gold'
WHERE id > (SELECT last_processed_id FROM bulk_job_progress WHERE job_name = 'tier_upgrade')
  AND id <= (SELECT last_processed_id FROM bulk_job_progress WHERE job_name = 'tier_upgrade') + 2000;

UPDATE bulk_job_progress
SET last_processed_id = last_processed_id + 2000, updated_at = now()
WHERE job_name = 'tier_upgrade';

COMMIT;
-- Repeat this batch until no more rows match the range

7. Locking-Verhalten bei Bulk-Operationen verstehen

Die meisten relationalen Datenbanken setzen bei kleinen Operationen Row-Locks, die nur die tatsaechlich betroffenen Zeilen sperren und parallele Zugriffe auf andere Zeilen problemlos zulassen. Steigt die Anzahl gesperrter Zeilen innerhalb einer Transaktion ueber einen internen Schwellenwert, eskalieren einige Datenbanksysteme, insbesondere SQL Server, automatisch auf einen Table-Lock, um den Verwaltungsaufwand der vielen einzelnen Row-Locks zu begrenzen. Ab diesem Moment blockiert die Bulk-Operation jeden anderen Zugriff auf die Tabelle, auch lesende Anfragen, was in einem produktiven System zu sichtbaren Ausfaellen fuehrt.

MySQL mit InnoDB und PostgreSQL kennen dieses klassische Lock-Eskalations-Verhalten in dieser Form nicht, haben aber ein verwandtes Problem: Ein sehr grosses UPDATE oder DELETE haelt seine Row-Locks bis zum Commit, und bei Millionen betroffener Zeilen kann das effektiv genauso blockierend wirken wie ein Table-Lock, einfach weil so viele Zeilen gleichzeitig gesperrt sind. Chunking mit haeufigen Commits ist deshalb unabhaengig vom konkreten Datenbanksystem die wirksamste Massnahme gegen blockierende Bulk-Operationen, weil Locks so nur fuer die kurze Dauer eines einzelnen Batches gehalten werden.

Bei Bulk-Operationen, die parallel zu regulaerem Anwendungsbetrieb laufen sollen, hilft zusaetzlich, die Isolation Level bewusst zu waehlen. Ein niedrigeres Isolation Level wie READ COMMITTED reduziert die Anzahl und Dauer gehaltener Locks gegenueber SERIALIZABLE erheblich und ist fuer die meisten Bulk-Loads voellig ausreichend, weil waehrend der Ladephase ohnehin selten gleichzeitig komplexe Leseanfragen mit strikten Konsistenzanforderungen laufen.

8. Monitoring und Fehlerbehandlung bei Bulk-Jobs

Jede produktive Bulk-Operation braucht ein Monitoring, das erkennt, wenn ein Batch fehlschlaegt, haengen bleibt oder ungewoehnlich lange dauert. Ein einfaches, aber wirksames Muster ist eine Fortschritts-Tabelle, die nach jedem erfolgreichen Batch den letzten verarbeiteten Schluessel und einen Zeitstempel festhaelt. Bricht der Job ab, kann er ab dem letzten festgehaltenen Punkt fortgesetzt werden, statt von vorne zu beginnen, was bei mehrstuendigen Migrationen den Unterschied zwischen einem kurzen Rerun und einem kompletten Neustart ausmacht.

Zusaetzlich lohnt sich die Ueberwachung von Datenbankmetriken waehrend der Bulk-Operation: Wachstum des Transaktionslogs, Anzahl aktiver Locks, Replikations-Verzoegerung und Sperrwartezeiten anderer Sessions. Steigen diese Werte ueber definierte Schwellen, sollte der Job automatisch pausieren oder seine Batch-Groesse reduzieren, statt unbeirrt weiterzulaufen und das produktive System zu gefaehrden. Diese Art von adaptivem Throttling ist bei besonders sensiblen Bulk-Operationen, etwa auf einer Tabelle mit hoher Schreiblast, oft wichtiger als die reine Verarbeitungsgeschwindigkeit.

9. Bulk-Operationen im direkten Vergleich

Die folgende Uebersicht fasst zusammen, welcher Ansatz fuer welche Groessenordnung und welches Risiko-Profil geeignet ist. Die Wahl haengt weniger von persoenlicher Vorliebe ab als von der konkreten Zeilenzahl, der Verfuegbarkeit von Wartungsfenstern und davon, ob das System waehrend der Verarbeitung produktiv erreichbar bleiben muss.

Ansatz Geeignet fuer Risiko Vorteil
Einzel-INSERT je Zeile Weniger als 100 Zeilen Sehr langsam bei grossen Mengen Einfachste Implementierung
Multi-Row-INSERT Tausende bis Hunderttausende Zeilen Gering, gute Balance Deutlich weniger Roundtrips
LOAD DATA / COPY Millionen Zeilen, initiale Ladung Gering bei leerer Zieltabelle Schnellster Bulk-Load-Mechanismus
Ungechunktes Massen-DELETE Nicht empfohlen ab wenigen Tausend Zeilen Lock-Eskalation, Log-Explosion Kein Vorteil gegenueber Chunking
Gechunktes DELETE/UPDATE Produktive Systeme, laufender Betrieb Gering, kontrollierbar Kurze Lock-Dauer je Batch
Partition Drop Partitionierte Tabellen, Milliarden Zeilen Gering, sofern korrekt partitioniert Nahezu sofortiges Loeschen

In der Praxis kombinieren robuste Migrations- und Wartungsskripte mehrere dieser Ansaetze: Multi-Row-INSERT oder COPY fuer die initiale Ladung, gechunkte UPDATEs fuer laufende Datenpflege und Partition Drop fuer periodisches Aufraeumen alter Daten. Die Wahl des richtigen Musters pro Situation ist der eigentliche Kern effizienter Bulk-Operationen, nicht ein einzelnes Patentrezept fuer alle Faelle.

Mironsoft

Datenbank-Performance, Migrationen und Bulk-Verarbeitung

Bulk-Operationen, die den Betrieb nicht ausbremsen?

Wir analysieren bestehende Massenverarbeitungs-Jobs, identifizieren Lock-Eskalation und Log-Explosion und bauen Batching-Strategien, die grosse Datenmengen verlaesslich und ohne Ausfallzeiten verarbeiten.

Performance-Audit

Analyse bestehender Bulk-Jobs auf Lock-Eskalation und Log-Wachstum

Batching-Design

Chunking-Strategien fuer INSERT, UPDATE und DELETE im laufenden Betrieb

Migrations-Support

Grossvolumige Datenmigrationen mit Monitoring und Rollback-Sicherheit

10. Zusammenfassung

Performante Bulk-Operationen entstehen nicht durch schnellere Hardware, sondern durch die richtige Struktur. Multi-Row-INSERT oder spezialisierte Bulk-Load-Werkzeuge ersetzen Einzel-Inserts, satzbasierte UPDATEs mit JOIN ersetzen Cursor-Schleifen, und gechunktes DELETE mit haeufigen Commits verhindert Lock-Eskalation und ein explodierendes Transaktionslog. Wo Indizes und Constraints den Vorgang dominieren, kann ihr temporaeres Deaktivieren bei initialen Ladungen erheblich Zeit sparen, sofern die Datenintegritaet anschliessend zuverlaessig wiederhergestellt wird.

Der groesste Hebel bleibt die bewusste Wahl der Batch-Groesse: gross genug fuer guten Durchsatz, klein genug, um Locks kurz zu halten und im Fehlerfall nicht Stunden an bereits verarbeiteter Arbeit zu verlieren. Monitoring von Log-Wachstum, Sperrwartezeiten und Replikations-Verzoegerung waehrend der Ausfuehrung macht Bulk-Operationen planbar, statt sie zu einem Risiko fuer den produktiven Betrieb zu machen.

Bulk-Operationen performant umsetzen, das Wichtigste auf einen Blick

Batching statt Einzelzeilen

Multi-Row-INSERT oder COPY/LOAD DATA statt einer Anweisung pro Zeile. Reduziert Roundtrips und Parsing-Overhead drastisch.

Chunking gegen Lock-Eskalation

Grosse UPDATE- und DELETE-Operationen in Batches von 1000 bis 10000 Zeilen mit eigenem Commit aufteilen.

Indizes bei initialer Ladung

Sekundaerindizes vor grossen Loads entfernen und danach neu aufbauen, statt sie inkrementell zu pflegen.

Monitoring waehrend der Laufzeit

Transaktionslog, Sperrwartezeiten und Replikations-Verzoegerung beobachten und Batch-Groesse adaptiv anpassen.

11. FAQ: Bulk-Operationen performant umsetzen

1Bulk-Insert vs. normales Insert?
Normales INSERT fuegt eine Zeile pro Anweisung ein. Bulk-Insert fasst viele Zeilen zusammen oder nutzt LOAD DATA/COPY, um Overhead zu minimieren.
2Wie gross sollte ein Batch sein?
1000 bis 10000 Zeilen bieten fuer die meisten Workloads eine gute Balance zwischen Durchsatz und Lock-Dauer. Messen statt raten.
3Warum Indizes vor Import deaktivieren?
Indizes werden bei jeder Zeile mitgepflegt. Ein Neuaufbau nach dem Laden ist bei Millionen Zeilen meist deutlich schneller.
4Was ist Lock-Eskalation?
Automatischer Wechsel von vielen Row-Locks zu einem Table-Lock. Blockiert dann jeden anderen Zugriff, auch lesende Anfragen.
5Millionen Zeilen loeschen ohne Stoerung?
In Chunks von einigen tausend Zeilen mit eigenem Commit loeschen. Bei partitionierten Tabellen ist Partition Drop noch schneller.
6Foreign Keys immer deaktivieren?
Nur bei garantiert konsistenter Datenquelle, und nach dem Laden zuverlaessig wieder aktivieren und validieren.
7Schnellster Weg fuer CSV-Import?
COPY (PostgreSQL), LOAD DATA INFILE (MySQL) oder BULK INSERT (SQL Server) umgehen den SQL-Parser weitgehend und sind am schnellsten.
8Umgang mit Fehlern im Bulk-Job?
Fortschritts-Tabelle mit letztem verarbeiteten Schluessel fuehren. Bei Abbruch ab dem letzten erfolgreichen Punkt fortsetzen.
9Bulk-Operationen und Replikation?
Grosse Operationen erzeugen grosse Replikationsbatches und erhoehen die Verzoegerung. Kleine, gestaffelte Chunks halten sie niedrig.
10Cursor bei Bulk-Updates sinnvoll?
Nur bei komplexer, nicht satzbasiert ausdrueckbarer Logik. Fuer reine Datenaenderungen ist satzbasiertes UPDATE mit JOIN fast immer schneller.