Was ist schneller, EXISTS vor oder nach dem INSERT?

8

Ich habe einen SP in SQL Server, der hunderte Male pro Minute läuft und eingehenden Datenverkehr gegen eine Datenbank prüfen muss. Im Moment macht es Folgendes:

%Vor%

Allerdings könnte ich auch mit

gehen %Vor%

Was wäre schneller? Ich habe das Gefühl, dass es nicht viel Unterschied zwischen ihnen gibt, aber ich bin historisch nicht sehr gut in TSQL ... = /

UPDATE: Whoops ... bedeutet, dass die EXISTS mehr als einen Wert verwenden, um herauszufinden, ob ein Datensatz existiert, so dass eine eindeutige Einschränkung nicht funktioniert. Bearbeitete die Probe, um das zu reflektieren ...

    
roryok 17.02.2010, 16:39
quelle

6 Antworten

1

Nachdem ich ein paar Kommentare zu dieser Frage und ihren Antworten hinzugefügt habe, werde ich meine eigenen Antworten geben.

Ich würde keinen größeren Leistungsunterschied zwischen den beiden in der ursprünglichen Frage vorgeschlagenen Vorschlägen erwarten. Auf der einen Seite, wie von Ray dargelegt, kann der zweite Ansatz Sie vor einigen Vorbereitungen für die Einfügung retten, aber auf der anderen Seite führt ein RDBMS normalerweise am besten mit Batch-Anweisungen aus, wie in der ersten Lösung.

KM und DVK schlagen vor, eine UNIQUE -Einschränkung hinzuzufügen, die den Eindeutigkeitstest implizit macht, aber Sie müssen eine Art Fehlerbehandlung für Ihre INSERT -Anweisung hinzufügen. Es fällt mir schwer zu erkennen, warum dies eine zusätzliche Leistung bringen sollte, vorausgesetzt, Sie haben bereits einen Index, der die zwei Spalten abdeckt . Wenn Sie keinen solchen Index haben, fügen Sie ihn hinzu und überdenken Sie, ob Sie mehr Leistung benötigen.

Ob die Eindeutigkeitsprüfung explizit oder implizit durchgeführt wird, sollte für AFAIK keine Rolle spielen. Wenn etwas erreicht wird, indem der Check "innerhalb" des Magens des DBMS durchgeführt wird, kann dieser Gewinn nur durch Overhead aufgefressen werden, der mit der Erhöhung und Handhabung von Fehlern verbunden ist, wenn Duplikate existieren.

Die Quintessenz: Unter der Annahme, dass ein Index bereits vorhanden ist, wenn Sie immer noch Lust auf Leistung finden, ist meine Empfehlung, dass Sie empirische Tests zu den drei vorgeschlagenen Lösungen durchführen. Kochen Sie ein kleines Programm, das die erwarteten Eingabedaten simuliert, und blasen Sie jede der drei Lösungen mit ein paar Milliarden Zeilen weg, einschließlich einer plausiblen Anzahl von Duplikaten. Tun Sie dies, achten Sie darauf, Ihre Ergebnisse zu veröffentlichen: -)

    
Jørn Schou-Rode 17.02.2010, 17:08
quelle
5

Beide Varianten sind falsch. Sie fügen Paare von Duplikaten @ value1, @ value2, garantiert ein.

Der richtige Weg, dies zu umgehen, besteht darin, eine eindeutige Einschränkung für zwei Spalten zu erzwingen und immer die Beschränkungsverletzung einzufügen und zu behandeln:

%Vor%

und einfügen:

%Vor%

Auch wenn dies kompliziert erscheinen mag, muss man ein kleines Detail mit dem Namen Korrektheit berücksichtigen. Dies ist viel einfacher im Vergleich zu einer Lock-Andeutungs-basierten Lösung. Dies ist auch die performanteste Lösung: Sucht nur einer. Alle anderen Lösungen benötigen mindestens zwei Suchvorgänge (einen, um zu bestätigen, dass sie eingefügt werden kann, und einen, um sie einzufügen).

    
Remus Rusanu 17.02.2010 19:03
quelle
3

In einer kaum gleichzeitigen Umgebung kann eine gleichzeitige INSERT zwischen IF NOT EXISTS und INSERT in Ihrer zweiten Abfrage auftreten.

Ihre erste Abfrage wird die freigegebenen Sperren auf den zu prüfenden Datensatz setzen, der erst am Ende der Abfrage aufgehoben wird. Daher ist es unmöglich, einen neuen Datensatz einzufügen, bis die Abfrage ausgeführt wird.

Sie sollten sich jedoch nicht ausschließlich auf dieses Verhalten verlassen. Fügen Sie eine zusätzliche UNIQUE -Einschränkung für value ein.

Dadurch wird die Datenbank nicht nur konsistenter, sondern es wird auch ein Index erstellt, der die erste Abfrage schneller macht.

    
Quassnoi 17.02.2010 17:09
quelle
1

tue es einfach und ignoriere irgendeinen Fehler (nimmt eine eindeutige Einschränkung für Value an) ...

%Vor%

Da hunderte Male pro Minute ausgeführt wird , sollten den SELECTs und einer Transaktion zu vermeide eine Race-Bedingung

%Vor%

Allerdings würde meine vorgeschlagene Idee, nur einen Fehler mit doppeltem Zwang einzufügen und zu ignorieren, auch eine Wettlaufbedingung vermeiden.

    
KM. 17.02.2010 16:47
quelle
0

Wenn Sie möchten, dass die Werte eindeutig sind, warum erstellen Sie nicht einfach eine eindeutige Einschränkung für den Wert, führen Sie einen INSERT ohne SELECT aus und behandeln Sie den Constraint-Verletzungsfehler ordnungsgemäß.

Das wäre schneller als einer dieser Ansätze.

Auch Ihre erste Annäherung funktioniert nicht - zu der Zeit, die Sie zu wählen, Sie bereits den Wert eingefügt haben, so wird offensichtlich finden, was Sie gerade eingefügt haben.

    
DVK 17.02.2010 16:44
quelle
0

Wenn ich raten müsste, würde ich annehmen, dass die zweite Option schneller wäre. sql server müsste für die Einfügung keinerlei Setups ausführen, wenn das Existieren fehlschlägt, während in der ersten Tabelle einige Tabellen- und Feldnamen nachschlagen und sich auf eine Einfügung vorbereiten könnte, die niemals stattfindet. Allerdings würde ich es im Query Analyzer versuchen und sehen, was der Plan sagt.

    
Ray 17.02.2010 16:45
quelle

Tags und Links