2016-08-18 74 views
-1

我有一个事件可以生成一些代表accumulators的数据,我称之为transaction。事实证明,从零开始生成累加器的运行速度要快于尝试将它们与现有累加器相匹配。因此,我给他们一个transaction_id,创建它们,然后在一个查询中删除以前的事务。Mysql快速插入,缓慢删除,错误索引

创建约。表中的200万行需要大约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,而是使用IDX_accumulator3,它不包含transaction_id

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我不使用交换内存,并具有约10GB剩余的可用内存,6GB分配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

假设你不想创建一个旧数据tabbles联合的视图(这在性能上很有意义会吸引),你可以使用state属性(可以从触发器驱动) – symcbean

+0

我结束了另一个表我在哪里记录所有交易及其状态。我现在用它来删除过期的交易,并且可以用'= @ transaction_id'而不是否定来确定匹配的记录。 – Hans