Ich arbeite mit SQL Server und Oracle. Es gibt wahrscheinlich einige Ausnahmen, aber für diese Plattformen lautet die allgemeine Antwort, dass Daten und Indizes gleichzeitig aktualisiert werden.
Ich denke, dass es hilfreich wäre, zu unterscheiden, wann die Indizes für die Sitzung, der die Transaktion gehört, und für andere Sitzungen aktualisiert werden. Standardmäßig werden in anderen Sitzungen die aktualisierten Indizes erst angezeigt, wenn die Transaktion festgeschrieben wurde. In der Sitzung, der die Transaktion gehört, werden jedoch sofort die aktualisierten Indizes angezeigt.
Betrachten Sie einen Tisch mit einem Primärschlüssel, um darüber nachzudenken. In SQL Server und Oracle wird dies als Index implementiert. Meistens möchten wir, dass sofort ein Fehler auftritt, wenn ein Fehler INSERT
auftritt, der den Primärschlüssel verletzt. Dazu muss der Index gleichzeitig mit den Daten aktualisiert werden. Beachten Sie, dass andere Plattformen wie Postgres verzögerte Einschränkungen zulassen, die nur überprüft werden, wenn die Transaktion festgeschrieben wird.
Hier ist eine kurze Oracle-Demo, die einen häufigen Fall zeigt:
CREATE TABLE X_TABLE (PK INT NULL, PRIMARY KEY (PK));
INSERT INTO X_TABLE VALUES (1);
INSERT INTO X_TABLE VALUES (1); -- no commit
Die zweite INSERT
Anweisung gibt einen Fehler aus:
SQL-Fehler: ORA-00001: Die eindeutige Einschränkung (XXXXXX.SYS_C00384850) wurde verletzt
00001.
00000 - "eindeutige Einschränkung (% s.% S) verletzt"
* Ursache: Eine UPDATE- oder INSERT-Anweisung hat versucht, einen doppelten Schlüssel einzufügen. Bei Trusted Oracle, das im DBMS MAC-Modus konfiguriert ist, wird diese Meldung möglicherweise angezeigt, wenn auf einer anderen Ebene ein doppelter Eintrag vorhanden ist.
* Aktion: Entfernen Sie entweder die eindeutige Einschränkung oder stecken Sie den Schlüssel nicht ein.
Wenn Sie eine Indexaktualisierungsaktion bevorzugen, finden Sie unten eine einfache Demo in SQL Server. Erstellen Sie zunächst eine zweispaltige Tabelle mit einer Million Zeilen und einem nicht gruppierten Index für die VAL
Spalte:
DROP TABLE IF EXISTS X_TABLE_IX;
CREATE TABLE X_TABLE_IX (
ID INT NOT NULL,
VAL VARCHAR(10) NOT NULL
PRIMARY KEY (ID)
);
CREATE INDEX X_INDEX ON X_TABLE_IX (VAL);
-- insert one million rows with N from 1 to 1000000
INSERT INTO X_TABLE_IX
SELECT N, N FROM dbo.Getnums(1000000);
Die folgende Abfrage kann den nicht gruppierten Index verwenden, da der Index ein Deckungsindex für diese Abfrage ist. Es enthält alle Daten, die zur Ausführung benötigt werden. Wie erwartet werden keine Rücksendungen zurückgegeben.
SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';
Starten wir nun eine Transaktion und aktualisieren sie VAL
für fast alle Zeilen in der Tabelle:
BEGIN TRANSACTION
UPDATE X_TABLE_IX
SET VAL = 'A'
WHERE ID <> 1;
Hier ist ein Teil des Abfrageplans dafür:
Rot eingekreist ist die Aktualisierung des nicht gruppierten Index. Blau eingekreist ist die Aktualisierung des Clustered-Index, bei dem es sich im Wesentlichen um die Daten der Tabelle handelt. Obwohl die Transaktion nicht festgeschrieben wurde, werden die Daten und der Index in einem Teil der Ausführung der Abfrage aktualisiert. Beachten Sie, dass dies in einem Plan nicht immer angezeigt wird, abhängig von der Größe der beteiligten Daten und möglicherweise anderen Faktoren.
Da die Transaktion noch nicht festgeschrieben ist, wiederholen wir die SELECT
Abfrage von oben.
SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';
Das Abfrageoptimierungsprogramm kann den Index weiterhin verwenden und schätzt diesmal, dass 999999 Zeilen zurückgegeben werden. Das Ausführen der Abfrage gibt das erwartete Ergebnis zurück.
Das war eine einfache Demo, aber hoffentlich hat es die Dinge ein bisschen geklärt.
Abgesehen davon sind mir einige Fälle bekannt, in denen argumentiert werden könnte, dass ein Index nicht sofort aktualisiert wird. Dies erfolgt aus Leistungsgründen und der Endbenutzer sollte keine inkonsistenten Daten sehen können. Beispielsweise werden Löschvorgänge manchmal nicht vollständig auf einen Index in SQL Server angewendet. Ein Hintergrundprozess wird ausgeführt und bereinigt schließlich die Daten. Sie können über Geisteraufzeichnungen lesen, wenn Sie neugierig sind.
Ich habe die Erfahrung gemacht, dass 1.000.000 Zeileneinfügungen tatsächlich mehr Ressourcen erfordern und länger dauern als bei Verwendung von Batch-Einfügungen. Dies könnte beispielsweise in 100 Einfügungen von 10.000 Zeilen implementiert werden.
Dies reduziert den Overhead der eingefügten Stapel und wenn ein Stapel ausfällt, handelt es sich um einen kleineren Rollback.
In jedem Fall gibt es für SQL Server ein Dienstprogramm bcp oder den Befehl BULK INSERT , mit dem Batch-Einfügungen durchgeführt werden können.
Natürlich können Sie auch Ihren eigenen Code für diesen Ansatz implementieren.
quelle