2011-02-18 1 views
1

내가 최근에 생각해 보았던 흥미로운 디자인 결정이 있습니다. 내가 테이블에 사용자 이름을 추가하고 중복되지 않도록하고 싶다고 가정 해 봅시다. 사용자 이름 열은 NOT NULL UNIQUE입니다. 내가 할 수 중 하나데이터베이스 오류를 통해 비즈니스 로직을 적용해야합니까?

  1. 쿼리 확인 중복 된 이름 또는
  2. 그냥 INSERT이 없는지 확인하고 데이터베이스 엔진에서 오는 예외를 잡기 위해 삽입하기 전에 데이터베이스.

내가 사용하고있어 DB 제약 조건을 적용 할 수있는 가정, 나는이 선택의 각각에 적합한 어떤 상황이 궁금 해서요.

답변

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 
+0

단순히 삽입을 수행하고 실패했는지 확인하는 것보다 두 개의 쿼리를 수행하는 것이 더 빠르다는 것을 의미합니까? 논리적으로 보이지 않기 때문에이를 보여주는 벤치 마크를보아야합니다. – corsiKa

+0

@glowcoder - 예, 있습니다. 예외 처리는 비용이 많이 들며, 예상치 못한 일이 발생했을 때 사용되도록되어 있습니다. 단일 행 검사는 일반적으로 예외 처리보다 비용이 적게 듭니다. –

+1

그러나 예외는 드문 경우이지만 인서트 작업이 더 일반적인 경우가 더 느립니다. – HLGEM

1

거의 항상 효과적으로 삽입을 수행하는 데 필요한 시간을 (모두 처음 읽는 필요) 두배로했기 때문에 내가 옵션 1을 권하고 싶지 않다 옵션 2를 할 수있는 좋은 아이디어처럼 보인다. 게다가, 일부 새로운 개발자는 언젠가 언젠가는 수표에 넣지 않을 것이며, 깨질 것입니다.

고려해야 할 또 다른 사항은 얼마나 많은 가동 중지 시간이 적절합니까? 이것은 임무에 중요한 응용 프로그램입니까? 비즈니스 로직이 손상되면 어떻게됩니까? 만약 공장이 폐쇄된다면? 아니면 그냥 성가신 버그일까요?

여러분이 생각 치지 않은 예외 때문에 서버를 종료 할 수 없으므로 공장을 폐쇄 할 여력이 없습니다. 따라서 데이터 정확성에 대한 야간 또는 주간 점검이이 경우에도 도움이 될 수 있습니다. 그러나 고유성 (및 잠재적으로 다른 강제력)을 시행하는 DB 기능이 적절한 방법이라고 생각합니다.

+0

필자는 삽입 전에 쿼리를 수행하는 것보다 예외를 잡는 것이 얼마나 비싼지에 대한 간단한 데모로 내 대답을 업데이트했습니다. 예외를 포착하는 것은 오라클에서 적어도 삽입 작업을 수행하는 데 필요한 시간의 두 배가 넘습니다. –

1

데이터베이스로 이동하지 않고 사용자 이름 목록을 캐시하고 응용 프로그램에서 확인할 수 있습니까? 불량 데이터가 들어오지 않도록 데이터베이스에 고유 한 제한 조건을 지정해야합니다 (항상 데이터베이스 수준의 데이터를 항상 보호해야합니다). 그러나 캐시에서 검사를 수행 할 수 있으면 전체 왕복 시간을 절약 할 수 있습니다. 누군가가 기존 사용자와 동일한 사용자 이름을 선택할 때 데이터베이스. 이제는 캐시해야 할 데이터의 크기와 캐시를 얼마나 자주 업데이트해야하는지에 따라 달라질 수 있습니다. 당신의 시스템을 알지 못한다면, 그것이 실용적이라고 말할 수는 없지만 적어도 그것을하는 것으로 보일 것입니다.