MySQL에서`REPLACE`와`INSERT… ON DUPLICATE KEY UPDATE`의 실질적인 차이점은 무엇입니까?


81

내가 필요한 것은 특정 키를 사용하여 레코드의 모든 필드 값을 설정하는 것입니다 (키는 실제로 복합입니다). 그러한 키가있는 레코드가 아직 없으면 레코드를 삽입합니다.

REPLACE작업을 수행하는 것처럼 보이지만 동시에 매뉴얼 페이지에서 INSERT ... ON DUPLICATE KEY UPDATE.

그들 중 무엇을 더 잘 선택해야하며 그 이유는 무엇입니까?

REPLACE내 마음에 떠오르는 유일한 "부작용"은 INSERT ... ON DUPLICATE KEY UPDATE아마도 자동 증가 값을 증가시키는 것입니다 (다행히도 저는 사용하지 않습니다) . 염두에 두어야 할 다른 실질적인 차이점은 무엇입니까? 어떤 특정 경우 REPLACE보다 선호 할 수 INSERT ... ON DUPLICATE KEY UPDATE있습니까?


INSERT ... ON DUPLICATE KEY UPDATE는 실제로 자동 증가 카운터를 증가시킵니다. 업데이트중인 레코드가 아니라 삽입 된 다음 레코드 용입니다. 따라서 가장 높은 ID가 10이고 중복 삽입을 수행 한 다음 새 고유 값을 삽입하면 해당 행의 ID는 12가됩니다.
marlar

답변:


117

REPLACE내부적으로 삭제를 수행 한 다음 삽입을 수행합니다. 해당 행을 가리키는 외래 키 제약 조건이있는 경우 이로 인해 문제가 발생할 수 있습니다. 이 상황에서 REPLACE실패하거나 더 나빠질 수 있습니다. 외래 키가 계단식 삭제로 설정된 경우 REPLACE다른 테이블의 행이 삭제됩니다. 이는 REPLACE작업 전후에 제약 조건이 충족 된 경우에도 발생할 수 있습니다 .

사용 INSERT ... ON DUPLICATE KEY UPDATE하면이 문제 를 피할 수 있으므로 선호됩니다.


1
좋은 대답이지만 실제 경우에는이 문제가 해결되지 않을 것입니다. 충돌 가능성은 50/50으로 간주 할 수 있습니다. 그러면 무엇을 선택해야합니까? 그리고 INSERT ... ON DUPLICATE KEY UPDATE상당히 "더 나은" 것처럼 보이지만 어떤 경우에 "REPLACE"가 더 나은 선택이 될 수 있습니까?
Ivan

3
나는 상당히 많은 연구를 해왔고 내가 말할 수있는 한 INSERT ... ON DUPLICATE KEY UPDATE 대신 REPLACE를 사용하는 일반적인 이유는 없습니다. 본질적으로 레거시 기능입니다. 코드가 삭제되고 다시 추가되는 행에 의존하는 특별한 이유가없는 한, 인덱스 및 자동 증가 값에 대한 관련 효과와 함께 사용할 이유가없는 것 같습니다.
Nathan Stretch

2
REPLACE당신의 PK 자동 증가 값을 업데이트합니다 그것은 않는 경우 DELETEINSERT. 정확히 내가 원하는 것입니다. 소비자가 동일한 PK에서 레코드를 찾는 것을 원하지 않으므로 행이 없습니다. 나는 그들이 (실제 업데이 트를) 찾을 때, 나는 사용UPDATE
radtek

그래서 질문의 나머지 절반은 언제 REPLACE보다 더 선호 INSERT ... ON DUPLICATE KEY UPDATE할까요? INSERT+ DELETE가 더 선호되는 이유는 무엇 UPDATE입니까?
LemonPi

59

성능 측면에서 질문에 답하기 위해 두 가지 방법을 모두 사용하여 테스트를 수행했습니다.

: 속으로는 포함 교체
테이블에 1.Try 삽입을
1이 실패 2. 경우, 삭제 행과 새로운 행 삽입

중복 키 업데이트에 삽입 포함 :
테이블에 1.Try 삽입
한 실패 2.If, 업데이트 행

과 관련된 모든 단계가있는 경우 삽입, 성능 차이가 없어야합니다. 속도는 관련된 업데이트 수에 따라 달라집니다. 최악의 경우는 모든 문이 업데이트되는 경우입니다.

62,510 개의 항목이 포함 된 InnoDB 테이블에서 두 문장을 모두 시도했습니다 (업데이트 만 해당).
캠핑 속도 : 다음으로 교체 : 77.411 초
중복 키 업데이트에 삽입 : 2.446 초

Insert on Duplicate Key update is almost 32 times faster.

테이블 크기 : Amazon m3.medium의 12 개 열이있는 행 1,249,250 개


멋진 통계, 시도해 보셨습니까 Insert on Duplicate Key Replace? 더 느렸습니까?
radtek jul.

@radtek 당신은 쓸 수만 있고 쓸 ON DUPLICATE KEY UPDATE수는 없습니다 ON DUPLICATE KEY REPLACE. 중복 키로 기존 행의 모든 ​​값을 업데이트하려면 작성 ON DUPLICATE KEY UPDATE col1=VALUES(col1), col2=VALUES(col2), ...해야합니다. 모든 열을 수동으로 나열해야합니다.
izogfif

나는 내가 무엇보다 더 빠르고 업데이트처럼 보이는 것을 묻는 것을 알고 있습니다.
radtek

9

REPLACE대신을 사용할 INSERT ... ON DUPLICATE KEY UPDATE때 주어진 키에 대해 여러 쿼리가 빠르게 도착할 때 키 잠금 또는 교착 상태 문제가 발생하는 경우가 있습니다. 후자의 원자 성은 (연쇄 삭제를 일으키지 않는 것 외에도) 그것을 사용하는 더 많은 이유입니다.


3

모든 열을 나열하지 않으면 REPLACE언급되지 않은 열을 대체 된 행의 기본값으로 재설정 할 것이라고 생각 합니다. ON DUPLICATE KEY UPDATE언급되지 않은 열은 변경되지 않습니다.


3

INSERT ... ON DUPLICATE KEY UPDATE보다 REPLACE를 선호하는 경우는 무엇이며 그 반대의 경우도 마찬가지입니까?

FEDERATED 스토리지 엔진 INSERT...ON DUPLICATE KEY UPDATE문이 있는 테이블의 경우 에는 허용되지만 실패 (오류 1022 : 쓸 수 없음, 테이블의 중복 키 ...)가 중복 키인 경우 실패 하는 어려운 방법을 방금 알아 냈습니다 . 위반 발생 -MySQL 참조 매뉴얼 의이 페이지 에서 해당 글 머리 기호를 참조하십시오 .

다행히도 삽입 후 트리거 REPLACE대신 사용 INSERT...ON DUPLICATE KEY UPDATE하여 변경 사항을 FEDERATED 테이블에 복제하는 원하는 결과를 얻을 수있었습니다 .


2

Replace는 키가 이미 존재하는 경우 두 가지 작업을 수행하는 것 같습니다. 아마도 그것은 둘 사이에 속도 차이가 있음을 의미합니까?

(INSERT) 하나의 업데이트 vs 하나의 삭제 + 하나의 삽입 (REPLACE)

편집 : 교체가 느릴 수 있다는 내 의미는 실제로 완전히 잘못되었습니다. 글쎄, 어쨌든이 블로그 게시물에 따르면 ... http://www.tokutek.com/2010/07/why-insert-on-duplicate-key-update-may-be-slow-by-incurring-disk-seeks /



0

INSERT IGNORE가 데이터 변환과 함께 작동하지 않는 것처럼 보이기 때문에 REPLACE가 때때로 필요한 것 같습니다.

이렇게하면 가장 큰 도시 팝을 자체로 설정합니다.

INSERT IGNORE INTO largerCities (stateID, maximumCityPop, statePop) SELECT stateID, MAX (city.pop) as maximumCityPop, state.pop FROM city JOIN state on city.stateID = state.ID GROUP BY city.stateID ON DUPLICATE KEY UPDATE 최대 CityPop = 최대 도시 팝

이렇게하면 GROUP 함수를 부적절하게 사용하고 있습니다.

INSERT IGNORE INTO maximumCities (stateID, maximumCityPop, statePop) SELECT stateID, MAX (city.pop) as maximumCityPop, state.pop FROM city JOIN state on city.stateID = state.ID GROUP BY city.stateID ON DUPLICATE KEY UPDATE maximumCityPop = MAX (city.pop)

이렇게하면 MySQL은 열 이름을 인식하지 못합니다.

INSERT IGNORE INTO largerCities (stateID, maximumCityPop, statePop) SELECT stateID, MAX (city.pop) as maximumCityPop, state.pop FROM city JOIN state on city.stateID = state.ID GROUP BY city.stateID ON DUPLICATE KEY UPDATE maximumCityPop = city .largestCityPop

이것은 작동하지만 그냥 추한 것 같습니다.

INSERT IGNORE INTO largerCities (stateID, maximumCityPop, statePop) SELECT * FROM (SELECT stateID, MAX (city.pop) as biggestCityPop, state.pop FROM city JOIN state on city.stateID = state.ID GROUP BY city.stateID) x ON 중복 키 업데이트 largeCityPop = biggestCityPop


주의 : 외부 제약 조건이 실패하면INSERT IGNORE 쿼리가 성공적으로 완료되고 경고 가 발생합니다 ! 이 같은 오류를보다 효율적으로 사용 잡을하려면 ON DUPLICATE KEY UPDATE않고를 IGNORE.
izogfif
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.