sql >> データベース >  >> RDS >> Sqlserver

アップサートのバージョンの選択/挿入:高い同時実行性のデザインパターンはありますか?

    LOCKを使用して、物事をシリアライズ可能にすることができますが、これにより同時実行性が低下します。最初に一般的な条件(「ほとんど挿入またはほとんど選択」)を試し、次に「修復」アクションを安全に処理してみませんか?つまり、「JFDI」パターン...

    ほとんどの場合、INSERTが予想されます(ボールパーク70-80%以上):

    挿入してみてください。失敗した場合、その行はすでに作成されています。 TRY / CATCHは重複を処理するため、並行性について心配する必要はありません。

    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
    

    主にSELECT:

    同様ですが、最初にデータを取得してみてください。データなし=INSERTは必要ありません。繰り返しますが、2つの同時呼び出しでINSERTを試行した場合、両方の行でTRY/CATCHハンドルが欠落していることがわかりました。

    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
    

    2つ目は繰り返されているように見えますが、非常に同時です。ロックは同じことを達成しますが、同時実行性を犠牲にして...

    編集:

    なぜしない MERGEを使用するには...

    OUTPUT句を使用すると、更新されたものだけが返されます。したがって、OUTPUT句のINSERTEDテーブルを生成するには、ダミーのUPDATEが必要です。多くの呼び出しでダミーの更新を行う必要がある場合(OPによって暗示されるように)、それは大量のログ書き込みです MERGEを使用できるようにします。



    1. SQLiteクエリ結果を列ヘッダー付きの列としてフォーマットする

    2. テーブルフィールドにハイフンを含めることはできますか?

    3. RedHatLinuxに複数のPostgreSQLサーバーをインストールする方法

    4. ローカルのphpMyAdminクライアントでリモートサーバーにアクセスするにはどうすればよいですか?