一意の列に値が存在するかどうかをチェックすることの長所と短所、または挿入時にdbに一意のエラーを発生させる


8

先日クエリを書いていると、思いが浮かんできてしまいました。

最初に一意の列の値が存在するかどうかを確認し、次に挿入するか挿入して、dbに一意の制約エラーを発生させますか?それは重要ですか?

編集:この問題はデータベースに依存するという回答で以下に示すように、タグpostgresqlを追加しています。

回答:


3

あなたの質問は本当にデータベースにとらわれていないと思います。正しい答えは、実装の詳細に依存する可能性があります。これは、ベンダーごとに異なり、次のバージョンで変わる可能性があります。RDBMSでアプローチを選択する前に、同時実行でテストします。

現在、SQL Server 2008 R2では、以下を使用しています。

  1. 同時実行性が低く、変更量が少ない。単一の行を保存するには、sp_getapplockを使用してシリアル化し、MERGEを使用します。それが機能することを確認するために、高い並行性の下でストレステストを行います。

  2. より高い同時実行性および/またはボリューム。並行性を回避し、パフォーマンスを向上させるために、一度に1行は保存しません。アプリサーバーに変更を蓄積し、TVPを使用してバッチを保存します。それでも、同時実行に関連する問題を回避するために、MERGEの前にsp_getapplockを使用してシリアル化します。繰り返しますが、私はそれが機能することを確認するために、高い並行性の下でテストを強調します。

その結果、本番環境ではパフォーマンスが高く、同時実行性に関連する問題はありません。デッドロック、PK /一意制約違反などはありません。


つまり、並行処理の問題が適切に処理されている場合は、最初にチェックすることをお勧めします。
codecool

1
はい、通常、エラーを回避することは、例外をスローしてキャッチすることよりも優れていますが、プラットフォームでそれをベンチマークする必要があります。
AK

7

DBにエラーを発生させます。

2つのスレッドが "NOT EXIST"を渡し、両方が書き込みを試みるため、最終的に衝突が発生するため、最初のテストは同時実行性に対して安全ではありません。これは、「READ COMMITTED」とMVCC / Snapshotロック戦略の両方に適用されます。

ロックヒントを使用して強制的に分離できますが、パフォーマンスは低下します。

これをJFDIパターン(SOリンク)と呼びます。「存在する場合は更新」については、こちらをご覧ください。SQLServer 2005のデッドロックシナリオのトラブルシューティングが必要です。これらはSQL Serverです。MySQLには、これを適切に処理するINSERT IGNOREがあります。残りはわからない


わかりました。そんなこと考えなかった!同時実行の場合、チェックも失敗する可能性があります。:)
codecool


チェックを実行する(そして正常に失敗する)ことは両方とも有用であると思いますが、「信頼するが検証する」という格言に従って失敗をキャッチします。理由?エラー処理は高価です。今日、いくつかのテストに取り組んでいますが、実際には、このコメントが理にかなっているかどうかが明らかになります。このコメントが消えると、結果がわかります。:-)
アーロンバートランド

また、2008年にはMERGE、Paulの見解を解決した可能性のあるものがありますが、これを高い送信レートでテストしていません。その構文を理解するように脳を訓練する必要があるためです。
アーロンバートランド

1
Mea culpa。今日、テストでいくつかの観察を行いました。これらは並行性のない非常に孤立したテストであることを覚えておいてください。ストレートインサートの場合、最初にチェックしてエラーを回避する方が、エラーを発生させるよりも約10倍高速です。しかし、より複雑なエラー処理を行う他のケース(TRY / CATCHまたはIF @@ ERROR <> 0、ROLLBACKまたはTHROWを使用するなど)では、最初にチェックした場合、約2倍遅くなります。繰り返しますが、これらは私の最初の観察に過ぎず、影響を与える可能性のある多くの要因があります。私はそれについて徹底的にブログを書くことができるようになるまでに時間がかかるかもしれません。
アーロンバートランド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.