1

私が最近考えている興味深いデザインの決定があります。ユーザー名をテーブルに追加していて、重複がないことを確認したいとしましょう。ユーザー名の列はNOT NULL UNIQUEです。次のいずれかが可能です。

  1. 挿入する前にデータベースにクエリを実行して、重複する名前がないことを確認するか、または
  2. だけINSERTで、データベース エンジンから発生するすべての例外をキャッチします。

私が使用しているDBが制約を適用できると仮定すると、これらの選択肢のそれぞれがどのような状況に適しているのか疑問に思っていました.

4

3 に答える 3

1

ほとんどの場合、オプション2を実行することをお勧めします。挿入を実行するのに必要な時間が実質的に2倍になったため、オプション1はお勧めしません(すべて最初に読み取りが必要です)。その上、何人かの新しい開発者は、チェックにではなく、いつかコミットするつもりであり、それは壊れます。

考慮すべきもう1つのことは、どのくらいのダウンタイムが適切かということです。これはミッションクリティカルなアプリですか?ビジネスロジックが破損している場合はどうなりますか?もしそうなら、工場は閉鎖されますか?それとも、それは単にいくつかの厄介なバグになるのでしょうか。

サーバーがクラッシュしたとは思わなかった例外があるため、工場をシャットダウンする余裕はありません。したがって、この場合、データの正確性を毎晩または毎週チェックすることも役立ちます。ただし、一意性を強制するDB機能(および場合によっては他の強制)が適切な方法だと思います。

于 2011-02-18T15:19:44.280 に答える
1

ユーザー名リストをキャッシュして、データベースにアクセスせずにアプリケーション側で確認できますか? 不正なデータが入らないようにするために、データベースに一意の制約を設定する必要があります (常にデータベース レベルでデータを保護することが何よりも重要です) が、キャッシュからチェックを行うことができれば、誰かが既存のユーザーと同じユーザー名を選択したとき。現在、これは、キャッシュする必要があるデータのサイズと、キャッシュを更新する必要がある頻度に依存する場合があります。あなたのシステムを知らないので、それが実用的かどうかはわかりませんが、少なくともそれを検討したいと思います.

于 2011-02-18T15:30:46.973 に答える
0

新しいユーザー名は一意である可能性が高いと思いますか?それとも重複する可能性がありますか?ユーザー名が一意である可能性が高い場合は、挿入を実行して例外をキャッチする方が効率的です。ユーザー名が重複している可能性が高い場合は、例外をキャッチしようとするよりも、重複をチェックする(そして、類似しているがまだ取得されていないユーザー名を探す可能性がある)方が効率的です。明らかに、異なるデータベースおよびそれらのデータベースの異なるバージョンは、相対確率に関して異なる損益分岐点を持っています。しかし、一般的に、誰もが一意のユーザー名を持っている会社のシステムを構築している場合は、挿入を実行して例外をキャッチします。Hotmailを構築している場合は、最初に重複を確認してください。

簡単なデモ(Oracle 11.2.0.1)は、挿入の前にチェックを実行してからデータを書き込むよりも、失敗した挿入を実行して例外を処理するのに約7倍のコストがかかることを示しています。

SQL> create table username_test (
  2    username varchar2(30) unique
  3  );

Table created.

SQL> set timing on;

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    l_cnt integer;
  3  begin
  4    for i in 1 .. 100000
  5    loop
  6      select count(*)
  7        into l_cnt
  8        from username_test
  9       where username = 'JCAVE';
 10      if( l_cnt = 0 )
 11      then
 12        insert into username_test( username )
 13          values( 'JCAVE' );
 14      end if;
 15    end loop;
 16* end;
SQL> /

PL/SQL procedure successfully completed.

Elapsed: 00:00:04.20
SQL> rollback;

Rollback complete.

Elapsed: 00:00:00.00

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    l_cnt integer;
  3  begin
  4    for i in 1 .. 100000
  5    loop
  6      begin
  7       insert into username_test( username )
  8          values( 'JCAVE' );
  9      exception
 10        when dup_val_on_index then
 11          null;
 12      end;
 13    end loop;
 14* end;
SQL> /

PL/SQL procedure successfully completed.

Elapsed: 00:00:29.58
于 2011-02-18T15:19:09.580 に答える