MySQL에서 UPDATE 쿼리를 일괄 처리하는 가장 효율적인 방법은 무엇입니까?


10

오랜 시간 동안 데이터베이스에 대한 많은 업데이트를 플러시 해야하는 응용 프로그램을 작성 중이며 쿼리를 최적화하는 방법을 고수했습니다. 현재는 INSERT INTO ... VALUES (..), (..) ON DUPLICATE KEY UPDATE모든 값을 하나의 쿼리로 일괄 처리하지만 큰 테이블에서 엄청나게 느리게 실행하는을 사용하고 있습니다. 실제로 행을 삽입 할 필요는 없습니다.

내가 본 다른 접근법은 업데이트를 사용 SET value = CASE WHEN...하는 것입니다 (질의를 작성하는 방식으로 인해 생성하기가 어려울 수 있으며 CASE수백 / 수천 키 의 성능에 대해 잘 모르겠습니다 ). 업데이트. 이 중 하나가 현재 방법보다 빠를까요?

내가 알 수있는 한, MySQL에서 이것을 수행하는 관용적이고 효율적인 방법은 없다는 사실에 당황합니다. 보다 빠른 방법이 실제로 없다면 ON DUPLICATE KEYPostgreSQL로 전환하고 UPDATE FROM구문을 사용하는 것이 가치가 있습니까?

다른 제안도 대단히 감사합니다!

편집 : 다음은 자주 업데이트되는 표 중 하나입니다. 관련이 없어서 열 이름을 제거했습니다.

CREATE TABLE IF NOT EXISTS `table` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `a` bigint(20) unsigned NOT NULL DEFAULT '0',
  `b` bigint(20) unsigned NOT NULL DEFAULT '0',
  `c` enum('0','1','2') NOT NULL DEFAULT '0',
  `d` char(32) NOT NULL,
  -- trimmed --
  PRIMARY KEY (`id`),
  KEY `a` (`a`),
  KEY `b` (`b`),
  KEY `c` (`c`),
  KEY `d` (`d`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

이것은 테스트 머신에 있지만 프로덕션 환경이 아니므로 InnoDB가 올바르게 조정되지 않았습니다. INSERT FROM이 어떻게 작동하는지 확실하지 않지만 당신이 말한 것이 옳아 보입니다. 요청한 정보로 질문을 업데이트했습니다.
jli

답변:


14

InnoDB테이블을 사용 하고 있으므로 가장 확실한 최적화는 여러 개의 UPDATE트랜잭션을 트랜잭션으로 그룹화하는 것 입니다.

함께 InnoDB트랜잭션 엔진 인, 당신은 단지 아니 지불 UPDATE자체뿐만 아니라 모든 트랜잭션 오버 헤드 : 트랜잭션 버퍼, 트랜잭션 로그를 관리하는 디스크에 로그를 플러시.

아이디어가 논리적으로 편안하다면 UPDATE한 번에 100-1000 s를 그룹화 하여 매번 다음과 같이 포장하십시오.

START TRANSACTION;
UPDATE ...
UPDATE ...
UPDATE ...
UPDATE ...
COMMIT;

가능한 단점 :

  • 하나의 오류는 전체 트랜잭션을 축소하지만 코드에서 쉽게 수정됩니다.
  • 1000 초가 누적 될 때까지 기다릴 수 있으므로 UPDATE시간 종료를 원할 수도 있습니다.
  • 응용 프로그램 코드가 더 복잡합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.