Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Select/Insert-Version eines Upsert:Gibt es ein Entwurfsmuster für hohe Parallelität?

Sie können LOCKs verwenden, um Dinge SERIALISIERBAR zu machen, aber dies reduziert die Parallelität. Warum nicht zuerst die allgemeine Bedingung ausprobieren ("meistens einfügen oder meistens auswählen"), gefolgt von einer sicheren Handhabung der "Abhilfe"-Maßnahmen? Das heißt, das "JFDI"-Muster...

Größtenteils INSERTs erwartet (normalerweise 70–80 %+):

Versuchen Sie einfach einzufügen. Wenn dies fehlschlägt, wurde die Zeile bereits erstellt. Sie müssen sich keine Gedanken über Parallelität machen, da TRY/CATCH Duplikate für Sie behandelt.

BEGIN TRY
   INSERT Table VALUES (@Value)
   SELECT @id = SCOPE_IDENTITY()
END TRY
BEGIN CATCH
    IF ERROR_NUMBER() <> 2627
      RAISERROR etc
    ELSE -- only error was a dupe insert so must already have a row to select
      SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH

Meistens SELECTs:

Ähnlich, aber versuchen Sie zuerst, Daten zu erhalten. Keine Daten =INSERT erforderlich. Nochmals, wenn 2 gleichzeitige Aufrufe INSERT versuchen, weil sie beide festgestellt haben, dass in der Zeile die TRY/CATCH-Handles fehlen.

BEGIN TRY
   SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
   IF @@ROWCOUNT = 0
   BEGIN
       INSERT Table VALUES (@Value)
       SELECT @id = SCOPE_IDENTITY()
   END
END TRY
BEGIN CATCH
    IF ERROR_NUMBER() <> 2627
      RAISERROR etc
    ELSE
      SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH

Der zweite scheint sich zu wiederholen, aber er ist sehr gleichzeitig. Sperren würden dasselbe erreichen, aber auf Kosten der Parallelität...

Bearbeiten:

Warum nicht um MERGE zu verwenden...

Wenn Sie die OUTPUT-Klausel verwenden, wird nur das zurückgegeben, was aktualisiert wurde. Sie benötigen also ein Dummy-UPDATE, um die INSERTED-Tabelle für die OUTPUT-Klausel zu generieren. Wenn Sie bei vielen Aufrufen Dummy-Updates durchführen müssen (wie von OP impliziert), ist das nur eine Menge Log-Schreibvorgänge um MERGE verwenden zu können.