2016-07-07 3 views
2

는 불행하게도 나는 어떻게이 질문의 이름을 더 좋은 생각이 없다, 그래서 당신은 더 나은이있는 경우 제안/원에 업데이트 가서 삽입하려고 할 때 나는이 방법을 사용하고있다 년 이후RDBM - 일대일 -> 항목이 있는지 확인하고 삽입/업데이트하거나 항상 삭제하고 삽입 만 하시겠습니까?

:-) 편집 - one resource : DELETE을 수행하여 그러한 PK가있는 행이없는 것을 확인한 다음 INSERT 만 수행하십시오. 나는 항상 이것이 성능과 단순성 모두를위한 최선의 사례라고 생각했습니다. DB 및 응용 프로그램 계층 (즉, DELETE 쿼리를 실행하면 SELECT을 실행하고 결과를 확인하는 것보다 비용이 적게 드는 것처럼 보입니다. 데이터가 양방향으로 전송되는 것을 고려할 때도 마찬가지입니다).

그러나 물론 다른 방법은 INSERT ... ON DUPLICATE KEY UPDATE ..., IF EXISTS (SELECT ...) UPDATE ... ELSE INSERT... 또는 UPDATE ... ;IF ROWCOUNT = 0 INSERT ...처럼 (기본 RDBMS에 따라) 및 응용 프로그램 계층에서 동일하게 수행 물론, 즉 먼저 확인을 항목이 있는지 여부와 그것이 UPDATE을 수행 않는 경우가 있습니다 , INSERT을 수행하거나 UPDATE을 수행하고 영향을받는 행의 수를 확인한 다음 0이 아니면 INSERT [UPDATE이 기본 리소스를 변경하지 않으면 영향을받는 행 수로 0을 반환하므로 INSERT은 다음을 반환합니다. 중복 PK 오류] ...

나는 무엇이 최선의 방법인지 궁금하다. 최선의 방법은 성능, 모범 사례 등을 고려하는 경우입니다.

답변

3

사용하는 것은 정상적인 일입니다. 간단하고 의도는 분명합니다. 읽기 쉽습니다. 또한 색인 항목을 변경할 필요가 없기 때문에 성능이 훨씬 향상됩니다.

을 사용하면 INSERT은 두 프로세스가 동일한 키를 동시에 업데이트하려고 시도 할 때 경쟁 상태에 취약하기 때문에 프로세스 중 하나에 대해 고유 한 키 위반이 발생합니다. 행이 물리적으로 삭제되고 새 행이 삽입되어야 할뿐만 아니라 색인 항목도 삭제되어야하고 삽입되어야하기 때문에 훨씬 느립니다.

IF EXISTS을 사용하면 저장 프로 시저 내에서 수행해야하므로 해당 호출 선택 항목에 고정되어 응용 프로그램으로 포팅 할 수 없으므로 좋은 선택이 아닙니다. 또한 ON DUPLICATE KEY UPDATE 내장 명령을 복제하려는 시도 일 뿐이므로 효율성이 떨어집니다.


는 이럴도 매우 중요하다 프로그래머 성능, 즉 효율성에 관한 언급을 응답. 당신이 매개 변수를 중복되지 않도록하려면

는 편의를 위해 약간의 리팩토링을 추가

stmt.setObject(3, "foo"); 
stmt.setObject(4, "bar"); 
stmt.setObject(5, 99); 
stmt.setObject(6, "foo"); 
stmt.setObject(7, "bar"); 
stmt.setObject(8, 99); 

:

applyTwice(stmt, 3, "foo", "bar", 99); 

가 효과적으로 작업을 수행합니다

void applyTwice(PreparedStatement stmt, int fromIndex, Object... values) { 
    for (int i = 0; i < values.length; i++) { 
     stmt.setObject(i + fromIndex, values[i]); 
     stmt.setObject(i + fromIndex + values.length, values[i]); 
    } 
} 

이 같은 호출 fromIndex 매개 변수는 리피터가 아닌 ids 등의 반복되지 않는 매개 변수를 허용합니다. 쿼리에서 ted.

void apply(PreparedStatement stmt, Object value, int... indexes) { 
    for (int i = 0; i < indexes.length; i++) { 
     stmt.setObject(indexes[i], value); 
    } 
} 

당신이 같이 부를 것이다 : :

또한 여러 인덱스에 하나의 값을 적용하는 간단한 방법 만들 수

apply(stmt, "foo", 3, 6); 
+0

확인을 특히에 대해 이야기 할 때, 나에게 합리적인 것 같다 공연. 그것은 하나의 배경을 가지고 있습니다 - 문을 준비하고 나서 * 모든 변수를 매개 변수로 제공하면서 * 실행 *하는 경우에 대비하여 '중복 키 업데이트'를 사용하여 복제해야합니다. 20 대신 10 매개 변수 ...하지만 성능을 목표로하므로 조금 더 입력하면 가치가 있습니다 :-) – shadyyx

+0

@shadyyx 입력 횟수를 두 배로 늘릴 수있는 몇 가지 방법을 추가했습니다. 코드에 대한 감사합니다. – Bohemian

+0

샘플,하지만 내 경우에는 (GoLang) 별도의 매개 변수 (예 :'stmt.setParam()'가 아니라'exec()'(예 :'stmt)로 전달하여 명명 된 매개 변수가 완전히 다른 해결책을 가져야합니다. Exec (param1, param2, param3, ..., paramX)'). 그렇지만, 단순히'array'를'slice'에 넣고,'stmt.Exec (params ...)'(말 그대로이 세개의 점들)처럼 전달할 수 있습니다. 그럼에도 불구하고 'INSERT ... DUPLICATE KEY UPDATE ...'명령은 ** REST PUT **에 어떻게 부합합니까? - 즉 리소스가 PUT 요청으로 대체됩니다. – shadyyx