MySQL优化INSERT速度因索引而减慢

Pee*_*aha 12 mysql sql indexing insert

MySQL Docs说:

假设B树索引,表的大小会减慢日志N的索引插入速度.

这是否意味着插入每个新行时,插入速度将减慢一个因子log N,其中N,我假设是行数?即使我只在一个查询中插入所有行?即:

INSERT INTO mytable VALUES (1,1,1), (2,2,2),  (3,3,3), .... ,(n,n,n)
Run Code Online (Sandbox Code Playgroud)

其中n是~70,000

我目前在一个表中有大约147万行,具有以下结构:

CREATE TABLE mytable (
   `id` INT,
   `value` MEDIUMINT(5),
   `date` DATE,
   PRIMARY_KEY(`id`,`date`)
) ENGINE = InnoDB
Run Code Online (Sandbox Code Playgroud)

当我在事务中以上述方式插入时,提交时间约为275秒.我如何优化这一点,因为每天都要添加新数据,插入时间将继续减慢.

此外,除了可能有帮助的查询之外,还有什么吗?也许一些配置设置?

可能的方法1 - 删除索引

我读到在插入之前删除索引可能有助于插入速度.插入后,我再次添加索引.但是这里唯一的索引是主键,在我看来放弃它对我来说没什么用.此外,当主键被删除时,所有选择的查询都将变得缓慢.

我不知道任何其他可能的方法.

编辑:这里有几个测试,在表中插入约~60,000行,行数约为1.47密耳:

使用上述简单查询: 146秒

使用MySQL的LOAD DATA infile: 145秒

使用MySQL的LOAD DATA infile并按照David Jashi的回答拆分csv文件:对于60个文件,每个1000行,136秒,对于6个文件,每个10,000行,136秒

删除和重新添加主键:密钥删除需要11秒,插入数据需要0.8秒,重新添加主键需要153秒,完全需要~165秒

N.B*_*.B. 18

如果你想快速插入,首先你需要的是适当的硬件.假设有足够的RAM,SSD而不是机械驱动器和相当强大的CPU.

由于你使用InnoDB,你想要的是优化它,因为默认配置是为慢速和旧机器设计的.

这是关于配置InnoDB的精彩内容

在那之后,你需要知道一件事 - 那就是数据库如何在内部完成他们的工作,硬盘驱动器的工作方式等等.我将在以下描述中简化机制:

一个事务是MySQL等待硬盘确认它写入数据.这就是机械驱动器上交易速度慢的原因,它们每秒可以进行200-400次输入输出操作.翻译,这意味着您可以在机械驱动器上使用InnoDB每秒获得200次插入查询.当然,这是简化的解释,只是为了概述正在发生的事情,它不是交易背后的完整机制.

由于查询(尤其是与表大小相对应的查询)在字节方面相对较小 - 您实际上在单个查询上浪费了宝贵的IOPS.

如果你在一个事务中包装多个查询(100或200或更多,没有确切的数字,你必须测试),然后提交它 - 你将立即实现每秒更多的写入.

Percona家伙在相对便宜的硬件上实现了每秒15k的插件.即使是5k插入一秒也不错.像你这样的表很小,我已经在类似的表上做了测试(3列以上),我设法获得10亿条记录没有明显的问题,使用16GB RAM机器和240GB SSD(1个驱动器,没有RAID,用于测试目的).

TL; DR: - 按照上面的链接,配置你的服务器,获得一个SSD,在1个事务中包含多个插入并获利.并且不要关闭索引然后再打开它,它总是不适用,因为在某些时候你将花费处理和IO时间来构建它们.

  • 事实证明我错了.我将默认的innodb_buffer_pool_size误认为是8G,实际上是8M.所以现在将它增加到5G之后,超过2分钟的查询很快就会在2秒内插入. (4认同)
  • 您拥有多个查询而不是一个大型查询的解决方案无济于事.插入时间是相同的.改变硬件也无法解决这个问题.我知道自己在做什么,我正在使用8G内存,1TB硬盘和相当强大的i3 CPU.另外,我不明白为什么我需要一个16G ram来将5Mb数据插入60Mb表?这太荒谬了. (2认同)
  • 我很高兴你调整了你的MySQL实例并且在没有重大硬件变化的情况下获得了有希望的结果,祝你们有更多的努力:) (2认同)

Dav*_*shi 5

无论如何,删除索引肯定会有所帮助。还可以考虑使用LOAD DATA。您可以在此处找到一些比较和基准

另外,在构造PRIMARY KEY时,请依次使用表中第一个字段,即切换结构中第二个和第三个字段的位置。