2016-08-18 1 views
-1

나는 transactionaccumulators을 나타내는 데이터를 생성하는 이벤트가 있습니다. 누산기를 처음부터 새로 생성하는 것보다 훨씬 빠르게 실행하는 것이 입증되었습니다. 따라서 나는 그들에게 transaction_id을 주었고 그들을 생성 한 다음 하나의 쿼리에서 이전 트랜잭션을 삭제합니다.빠른 삽입, 느린 삭제, 잘못된 인덱스

약. 표에서 2 백만 행은 약 40 초가 필요하지만 삭제는 현재 아래 쿼리를 사용하여 약 20-30 분이 소요됩니다.

DELETE 
    FROM accumulator 
WHERE id_acca_set = @set_id 
    AND (transaction_id != @transaction_id or transaction_id is null); 

innodb 상태를 살펴보면 쿼리가 실행될 때 다음과 같이 표시됩니다. 내가 알 수있는 한이 단계에서는 상충되는 자물쇠가없는 것 같습니다.

---TRANSACTION 11535589892, ACTIVE 259 sec updating or deleting, thread declared inside InnoDB 4657 
mysql tables in use 1, locked 1 
29009 lock struct(s), heap size 3776720, 1195753 row lock(s), undo log entries 1195753 
MySQL thread id 108262, OS thread handle 131874376460032, query id 9689717638 event_scheduler updating 

accumulator 표는하기와 같이 정의된다. 나는 IDX_accumulator5을 사용하지 않고 transaction_id을 포함하지 않고 IDX_accumulator3을 사용하고있는 것으로 나타났습니다.

CREATE TABLE acca.accumulator (
id bigint(20) NOT NULL AUTO_INCREMENT, 
id_acca_set int(1) NOT NULL DEFAULT 0, 
id_event bigint(20) NOT NULL DEFAULT 0, 
id_back_outcome bigint(20) NOT NULL DEFAULT 0, 
id_lay_outcome bigint(20) NOT NULL DEFAULT 0, 
acca_id varchar(255) DEFAULT NULL, 
prev_acca_id varchar(255) DEFAULT NULL, 
leg_number int(11) NOT NULL, 
score double DEFAULT NULL, 
transaction_id varchar(255) DEFAULT NULL, 
PRIMARY KEY (id), 
INDEX IDX_accumulator (id_acca_set, acca_id, transaction_id), 
INDEX IDX_accumulator2 (id_acca_set, leg_number, acca_id, transaction_id), 
INDEX IDX_accumulator3 (id_acca_set, id_event, id_back_outcome, id_lay_outcome, leg_number), 
INDEX IDX_accumulator4 (id_acca_set, prev_acca_id, id_event), 
INDEX IDX_accumulator5 (id_acca_set, transaction_id), 
INDEX IDX_accumulator6 (transaction_id, id_acca_set, leg_number, score) 
) 
ENGINE = INNODB 
AUTO_INCREMENT = 242051170 
AVG_ROW_LENGTH = 282 
CHARACTER SET utf8 
COLLATE utf8_general_ci 
ROW_FORMAT = DYNAMIC; 

내가 CentOS는 7에서 MySQL 5.7.13를 실행하고 내가 스왑 메모리를 사용하고 10기가바이트 무료 메모리를 나머지에 대해이없는이 6기가바이트는 INNODB 버퍼에 할당됩니다. my.cnf에서 InnoDB의 설정은 다음과 같습니다

innodb_buffer_pool_size = 6G 
innodb_buffer_pool_instances = 6 
innodb_commit_concurrency = 4 
innodb_flush_method = O_DIRECT 
innodb_thread_concurrency = 8 
innodb_thread_sleep_delay = 100 
innodb_flush_log_at_trx_commit = 1 
innodb_flush_log_at_timeout = 10 
+0

행 2.000.000을 삭제해야한다고 말하고 있습니까? – scaisEdge

+0

제목은시와 같이 읽습니다. D –

답변

1

나는 (! TRANSACTION_ID = @transaction_id)를 부정 술어를 해결하기 위해 인덱스를 사용하는 모든 DBMS 잘 모르는 것 같아요.

새 레코드를 추가하는 이유가 무엇인지 이해할 수 없습니다. 다음에 이전 레코드를 삭제하는 것은입니다. 당신이 그것을 다른 방법으로하면 (테이블 잘라 버림) 시간이 조금 걸립니다. 데이터를 다시 사용하려면 기존 테이블의 이름을 바꾸고 새 데이터를 보관할 새 테이블을 만듭니다 (원래 이름 사용).

+0

나는 테이블을 잘라내어 제안한 것을 정확하게 수행한다고 생각했지만 여러 개의 acca 세트가 있으며 테이블의 이름을 완전히 바꿀 수는 없습니다. 또한 새 집합을 생성 한 후에는 새 transaction_id를 사용하도록 다른 계산을 전환해야합니다. 이는 여러 가지 이유로 하나의 트랜잭션에서 수행 할 수 없습니다. – Hans

+1

이전 데이터 Tabble (성능이 좋지 않을 경우 의미가 있음)의 유니온 뷰를 만들지 않으려는 경우 상태 속성 (트리거에서 벗어날 수 있음)을 사용할 수 있음 – symcbean

+0

다른 테이블 여기서 모든 거래와 그 상태를 기록합니다. 나는 그것을 만료 된 트랜잭션을 지우는 데 사용하며, 부정한 레코드가 아닌'= @ transaction_id'로 일치하는 레코드를 찾아 낼 수 있습니다. – Hans