MySQL插入性能在大型表上降级

Sha*_*ore 16 mysql performance innodb

我正在使用一个拥有超过250万行的巨大桌子.架构很简单.

CREATE TABLE MyTable (
        id BIGINT PRIMARY KEY AUTO_INCREMENT,
        oid INT NOT NULL,
        long1 BIGINT NOT NULL,
        str1 VARCHAR(30) DEFAULT NULL,
        str2 VARCHAR(30) DEFAULT NULL,
        str2 VARCHAR(200) DEFAULT NULL,
        str4 VARCHAR(50) DEFAULT NULL,
        int1 INT(6) DEFAULT NULL,
        str5 VARCHAR(300) DEFAULT NULL,
        date1 DATE DEFAULT NULL,
        date2 DATE DEFAULT NULL,
        lastUpdated TIMESTAMP NOT NULL,
        hashcode INT NOT NULL,
        active TINYINT(1) DEFAULT 1,
        KEY oid(oid),
        KEY lastUpdated(lastUpdated),
        UNIQUE KEY (hashcode, active),
        KEY (active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 MAX_ROWS=1000000000;
Run Code Online (Sandbox Code Playgroud)

插件的性能显着下降.表中有多达1.5亿行,过去需要5-6秒才能插入10,000行.现在已经上升了2-4倍.Innodb的ibdata文件已增长到107 GB.Innodb配置参数如下.

innodb_buffer_pool_size = 36G # Machine has 48G memory
innodb_additional_mem_pool_size = 20M
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_file_size = 50M
innodb_log_buffer_size = 20M
innodb_log_files_in_group=2
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
innodb_thread_concurrency = 8
innodb_flush_method = O_DIRECT
expire_logs_days = 4
Run Code Online (Sandbox Code Playgroud)

IO等待时间已经上升了top.我已经尝试将flush方法更改为O_DSYNC,但它没有帮助.磁盘由硬件RAID 10设置构成.在早期的单磁盘设置中,IO不是问题.

是否只分区表选项?可以将单个100G文件拆分成"较小"的文件有帮助吗?是否有任何需要针对RAID调整的变量?

更新:这是一个测试系统.我可以自由地进行任何更改.

Mar*_*rkR 16

你没有说这是一个测试系统还是生产; 我假设它的生产.

您可能已经将表格调整到其索引(或整个批次)不再适合内存的大小.

这意味着InnoDB必须在插入期间读取页面(取决于新行的索引值的分布).阅读页面(随机读取)非常慢,如果可能,需要避免.

分区似乎是最明显的解决方案,但MySQL的分区可能不适合您的用例.

您当然应该考虑所有可能的选项 - 将表格放到实验室中的测试服务器上以查看其行为.

您的主键看起来好像可能不需要(您有另一个唯一索引),因此消除它是一个选项.

还要考虑innodb插件和压缩,这将使你的innodb_buffer_pool更进一步.

您真的需要分析您的用例,以确定您是否确实需要保留所有这些数据,以及分区是否是一个明智的解决方案.

对此应用程序进行任何更改可能会为您的用户带来新的性能问题,因此您需要在此处非常小心.如果您找到提高插入性能的方法,则可能会降低搜索性能或其他操作的性能.在发布此类更改之前,您需要对生产级硬件进行全面的性能测试.


abd*_*lar 5

根据我使用 Innodb 的经验,即使您拥有真正优化的磁盘子系统,它似乎也达到了写入密集型系统的限制。我很惊讶你居然能把它增加到 100GB。

这就是 Twitter 不久前遇到的问题,并意识到它需要分片 - 请参阅http://github.com/twitter/gizzard

这一切都取决于您的用例,但您也可以从 mysql 迁移到 cassandra,因为它对于编写密集型应用程序表现非常好。(http://cassandra.apache.org)