MySQL:为什么插入数据比没有它们更快

Zby*_*nek 4 mysql stored-procedures transaction

我正在使用存储过程生成由给定范围内的前缀和数字组成的序列(等序列“AB100”、“AB101”、...、“AB199”、“AB200”)

存储过程包括REPEAT循环,其中构造字符串并插入表中。

当所有循环都在事务内时,程序运行得非常快,但是当我在没有事务的情况下插入数据时,运行该程序的时间要长 400 倍。

谁能解释一下,为什么会这样?

或者,如果有人更好地了解如何生成这样的序列,我会很高兴听到他们的声音。

这是代码:

-- create table
CREATE TABLE seq
(
    Code CHAR(12)
) ENGINE = INNODB;

-- fast procedure with transactions
DELIMITER $$
CREATE PROCEDURE sp_sequence(IN val_prefix CHAR(2), IN val_from INT, IN val_to INT )
BEGIN
    START TRANSACTION;
    SET @val = val_from;
    REPEAT
        INSERT INTO seq (Code) VALUES (CONCAT(val_prefix, @val));
        SET @val = @val + 1;
    UNTIL @val > val_to END REPEAT;
    COMMIT;
END$$
DELIMITER ;

-- slow procedure without transactions
DROP PROCEDURE IF EXISTS sp_sequence_slow;
DELIMITER $$
CREATE PROCEDURE sp_sequence_slow(IN val_prefix CHAR(2), IN val_from INT, IN val_to INT )
BEGIN
    SET @val = val_from;
    REPEAT
        INSERT INTO seq (Code) VALUES (CONCAT(val_prefix, @val));
        SET @val = @val + 1;
    UNTIL @val > val_to END REPEAT;
END$$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)

以下是结果:

mysql> CALL sp_sequence('TX', 11000, 12000);
Query OK, 0 rows affected (0.09 sec)

mysql> CALL sp_sequence_slow('TX', 11000, 12000);
Query OK, 0 rows affected (40.07 sec)
Run Code Online (Sandbox Code Playgroud)

jka*_*lik 8

没有显式事务,所有语句都处于自动提交模式 - 因此每个插入都是单独的事务。这会带来一些同步等开销。

如果您插入所有行而不在其间提交,mysql 可以在内存/缓存中执行大量操作,并且仅将其同步到磁盘一次(简化,文件系统和操作系统可能会多次刷新缓存)。

在没有显式事务的情况下,每个插入都必须等待磁盘在返回之前确认写入所有更改并让循环继续。有时可以通过在每次事务后定期刷新来稍微放松一下,但您可能会在 IIRC 失败时丢失一些数据。

另一方面 - 如果您在一个事务中插入/更新太多行,包含可能回滚的信息的日志可能会增加很多并减慢一切。所以事务大小应该是合理的(而不是数百万行)。

一些提示:http : //dev.mysql.com/doc/refman/5.5/en/optimizing-innodb-transaction-management.html