为什么INSERTS进入我的MySQL表需要这么长时间

时间:2015-03-05 12:42:43

标签: mysql optimization

我正在构建一个MySQL帐户数据库。我有一个例程从json文件导入整个数据库。例程在单个事务中运行, 删除每个表中的所有记录,调用:

ALTER TABLE <tablename> AUTO_INCREMENT = 1

在每个表上,然后使用INSERT语句(如

)从数据加载表
INSERT INTO Journal (idJournal, DocumentId, AccountId, Memo, JournalNum,
 Amount, Outstanding, Cleared, NameAddressId) 
 VALUES (11423, 4454, 14, 'Deposit', 1, 53.33, 53.33, 'X', 292)

(请注意,表格按正确顺序加载,因此相关记录已经存在)。

我发现插入语句需要很长时间(有些时间长达70毫秒),特别是与从mysqldump加载相同数据相比。

我能做些什么来加快速度(除了使用mysqldump,我不想这样做,因为我希望备份数据是json格式的)?

表格定义:

  CREATE TABLE IF NOT EXISTS `accounts`.`Journal` (
    `idJournal` INT NOT NULL AUTO_INCREMENT,
    `DocumentId` INT NOT NULL,
    `AccountId` INT NOT NULL,
    `Memo` VARCHAR(45) NULL,
    `JournalNum` INT NOT NULL,
    `Amount` DECIMAL(10,2) NOT NULL,
    `Outstanding` DECIMAL(10,2) NOT NULL DEFAULT 0,
    `Cleared` CHAR(1) NOT NULL,
    `NameAddressId` INT NULL,
    PRIMARY KEY (`idJournal`),
    INDEX `fk_Journal_Document1_idx` (`DocumentId` ASC),
    INDEX `fk_Journal_Account1_idx` (`AccountId` ASC),
    UNIQUE INDEX `Document_Num` (`DocumentId` ASC, `JournalNum` ASC),
    INDEX `fk_Journal_NameAddress1_idx` (`NameAddressId` ASC),
    CONSTRAINT `fk_Journal_Document1`
   FOREIGN KEY (`DocumentId`)
   REFERENCES `accounts`.`Document` (`idDocument`)
   ON DELETE NO ACTION
   ON UPDATE NO ACTION,
    CONSTRAINT `fk_Journal_Account1`
   FOREIGN KEY (`AccountId`)
   REFERENCES `accounts`.`Account` (`idAccount`)
   ON DELETE NO ACTION
   ON UPDATE NO ACTION,
    CONSTRAINT `fk_Journal_NameAddress1`
   FOREIGN KEY (`NameAddressId`)
   REFERENCES `accounts`.`NameAddress` (`idNameAddress`)
   ON DELETE NO ACTION
   ON UPDATE NO ACTION)
  ENGINE = InnoDB

2 个答案:

答案 0 :(得分:1)

执行多次插入时,在单个语句中插入多行更有效,特别是如果您有很多二级索引:

INSERT INTO Journal (idJournal, DocumentId, AccountId, Memo, JournalNum,
  Amount, Outstanding, Cleared, NameAddressId) 
VALUES (11423, 4454, 14, 'Deposit', 1, 53.33, 53.33, 'X', 292),
       (11424, 4455, 15, 'Deposit', 1, 23.33, 23.33, 'X', 293),
       ...

这样,索引只更新一次(在语句末尾),而不是每次插入后。

如果您的数据库增长超过1GB,您将遇到问题,因为您已达到max_allowed_packet的限制。在这种情况下,您可能需要将其分解为多个查询。

当你说'#34;删除所有记录&#34;时,我希望你的意思是删除表或截断表,而不是实际删除所有记录。

答案 1 :(得分:0)

这适用于“no”中断表的使用:

  1. CREATE TABLE new LIKE real;
  2. 通过批量INSERT(或其他)加载new
  3. RENAME TABLE real TO old, new TO real; - 瞬时和原子
  4. DROP TABLE old;
  5. 没有TRUNCATE,没有AUTO_INCREMENT = 1