지금껏 단순하게 update 가 insert on duplicate key update 구문보다 더 빠를 것이라 생각했습니다. 물론 update의 조건절(where)에는 pk가 주어지는 상태일 경우를 말합니다.

테이블 구조는

  1. CREATE TABLE egg_table (
  2. url varchar(255) NOT NULL default '',
  3. title varchar(255) default NULL,
  4. PRIMARY KEY (url)
  5. ) ENGINE=MyISAM

입니다. 그리고 흔하게 사용하는

  1. 존재하는가 = select title from egg_table where url = 'http://egg.pe.kr/XXX';
  2. if 존재하는가 == 응 {
  3. update egg_table set title = 'new title' where url = 'http://egg.pe.kr/XXX';
  4. } else {
  5. insert into egg_table (title, url) values ('new title', 'http://egg.pe.kr/XXX');
  6. }

형태의 로직을 좀더 깔끔하게 해보려고

  1. insert into egg_table (title, url) values ('new title', 'http://egg.pe.kr/XXX') on duplicate key update title = 'new title';

를 사용해서 잘 사용하고 있었는데요. 문득 이런 생각이 들었습니다.

insert하는 경우보다 update하는 경우가 압도적을 많은 경우 오히려 update 한 후 insert를 하는 게 조금더 효과적이지 않을까 하는 그런 생각. 그래서

  1. update egg_table set title = 'new title' where url = 'http://egg.pe.kr/XXX';
  2. if 바뀐 rows 수 == 0 {
  3. insert into egg_table (title, url) values ('new title', 'http://egg.pe.kr/XXX');
  4. }

를 해봤는데요. 잘 되는 것 같았지만 일단 update 구문을 실행할 경우 새로 바뀌는 데이터가 없을 때 바뀐 row의 수는 0입니다. 따라서 duplicate key 오류를 반환하지요.

하지만!! 무조건! 항상! 바뀌는 경우는 update 후 없는 경우만 insert하는 것이 더 효과적이지 않을까 라는 생각을 해보려고 실제 테스트를 해보았습니다.

정말 정말 단순하게 3000번의 query를 요청해서 -_-ㅋ

  1. for (i = 0; i < 3000; i++) {
  2. update ....

    if affected rows num == 0 then insert ....

  3. }
  4. for (i = 0; i < 3000; i++) {
  5. insert .... on duplicate key update ...
  6. }

결과는... 대충 2.0221 대 1.1518 이라는 수가 나왔습니다. 다시말해 insert ... on duplicate key update 가 빠르다는 결론이 나왔습니다. 물론 요청 하나에 하나의 query만 실행한다면 별다른 차이는 없겠지만 여하튼 예상했던 결과와는 다르게 나왔습니다.

제가 잘못 테스트 한 것일까요... 음...

  1. ENGINE=MyISAM
    엔진 종류에 따라서 차이가 있지 않을까요?

    그리고 index 에 접근하는 횟수 차이라던가.. 음.. 생각좀 더 해봐야겠네요 :)

    2010.06.16 18:03 신고 [ ADDR : EDIT/ DEL : REPLY ]
  2. 슈럭

    엔진에 상관없이 insert ... on duplicate key update . 이 빠를수 밖에 없습니다.

    insert 문장의 처리속도를 1로 생각하고 update 쿼리문의 처리속도를 2로 가정합니다. 그리고 쿼리 문장을 전송하는 처리속도는 일단 무시하겠습니다.

    100개의 쿼리를 실행하는데 중복이 50개라고 할 때...
    1. insert... on duplicate key update 를 사용했을경우
    (100*1) + (50*2) = 200 입니다.

    2. update and insert를 사용할 경우 에는
    (100*2) + (50*1) = 250 입니다.

    단순히 보아도 insert... on dup.... 가 빠르다는것을 알수 있습니다.
    또 여기에 쿼리 문장을 전송하는 것을 생각하면
    1. 의 경우에는 100회 전송이고 2.의 경우에는 150회를 전송해야 합니다.
    만약 db서버가 원격지에 존재한다면 더욱 차이가 날수 밖에 없을겁니다.

    여기서 먼저 알아 둬야 할 것은 insert 문장이 select, update, delete 보다 빠르다는 것입니다.
    모두 동일한 속도를 가진다고 하여도 쿼리요청에 대한 수로 인해 1.의 경우가 2.의 경우보다 빠릅니다.

    2010.08.27 14:30 신고 [ ADDR : EDIT/ DEL : REPLY ]

댓글을 달아 주세요

티스토리 툴바