You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

为搭载超大InnoDB表的专用MariaDB服务器寻求最优配置方案

嘿,我来帮你捋捋这个问题——你的服务器硬件配置其实挺够用的,问题大概率出在无索引的超大InnoDB表嵌套查询的写法上,毕竟InnoDB对无索引的大表操作简直是灾难,尤其是嵌套SELECT这种容易触发多次全表扫描的操作。下面给你几个一步步解决的思路:

一、先紧急优化当前的数据迁移操作
  • 放弃嵌套SELECT,改用分批次批量处理
    嵌套查询尤其是关联大表时,很容易让数据库做笛卡尔积或者反复全表扫描,直接把操作拆成分批次的单表查询+批量插入会靠谱很多:
    比如假设原表有个自增id字段,每次取1000条数据迁移:
    INSERT INTO 克隆库.目标表
    SELECT * FROM 原库.原表
    WHERE id BETWEEN 1 AND 1000;
    
    循环执行这个语句,每次把范围往后挪1000,直到取完所有数据。这样每次操作的数据量小,不会把内存和CPU占满,也不会因为单次全表扫描锁表太久。
  • 临时给原表加辅助索引(如果业务允许)
    既然原表没合理建索引,如果你能停掉其他对原表的写入操作,临时加一个用于迁移的索引(比如你用来分批次的字段),会极大加快查询速度。迁移完成后再删掉这个临时索引就行:
    ALTER TABLE 原库.原表 ADD INDEX idx_temp(id);
    
    注意:加索引会锁表,建议选业务低峰期操作,或者用ALTER TABLE ... ALGORITHM=INPLACE(MariaDB10.1支持InnoDB的在线DDL)来减少锁表时间。
二、调整MariaDB配置,适配你的50G内存硬件

默认的MariaDB配置肯定没用到这么大的内存,调整几个关键参数能大幅提升性能:

  • innodb_buffer_pool_size:InnoDB最核心的参数,建议设为内存的70%-80%(也就是35G-40G),让大表数据尽量缓存在内存里,减少磁盘IO:
    innodb_buffer_pool_size = 35G
    
  • innodb_log_file_size:增大redo log大小,减少刷盘频率,建议设为2G-4G(不要超过buffer pool的1/4):
    innodb_log_file_size = 4G
    
  • innodb_log_buffer_size:如果批量插入数据多,这个可以设大一点,比如64M:
    innodb_log_buffer_size = 64M
    
  • max_heap_table_sizetmp_table_size:如果查询用到临时表,把这两个设为4G左右,避免临时表写到磁盘上拖慢速度:
    max_heap_table_size = 4G
    tmp_table_size = 4G
    

修改完配置后重启MariaDB生效。

三、换更高效的数据迁移方式,比INSERT/REPLACE快得多

如果数据量特别大,普通INSERT不是最高效的,试试这些方法:

  • 用mysqldump+mysql导入
    导出时加参数减少内存占用,导入时禁用索引和外键检查加速:
    # 导出原表,--quick逐行取数据不占内存,--single-transaction让InnoDB无需锁表
    mysqldump -u用户名 -p 原库 原表 --quick --single-transaction > 原表.sql
    # 导入到克隆库
    mysql -u用户名 -p 克隆库 <<EOF
    SET FOREIGN_KEY_CHECKS=0;
    SET UNIQUE_CHECKS=0;
    SOURCE 原表.sql;
    SET FOREIGN_KEY_CHECKS=1;
    SET UNIQUE_CHECKS=1;
    EOF
    
  • 用SELECT ... INTO OUTFILE + LOAD DATA INFILE
    这是比mysqldump更快的方式,直接在服务器本地生成文件再加载:
    -- 导出原表到服务器本地文件
    SELECT * INTO OUTFILE '/tmp/原表数据.txt'
    FIELDS TERMINATED BY ',' ENCLOSED BY '"'
    LINES TERMINATED BY '\n'
    FROM 原库.原表;
    
    -- 导入到克隆库
    LOAD DATA INFILE '/tmp/原表数据.txt'
    INTO TABLE 克隆库.目标表
    FIELDS TERMINATED BY ',' ENCLOSED BY '"'
    LINES TERMINATED BY '\n';
    
    注意要确保MariaDB有读写/tmp目录的权限,导入前同样可以禁用外键和唯一检查。
四、后续预防:给目标表建合理索引

迁移完成后,一定要根据后续的查询需求给目标表建好索引——比如经常用来过滤、排序、关联的字段,都要建对应的索引,避免以后再遇到同样的慢查询问题。

内容的提问来源于stack exchange,提问作者Erce

火山引擎 最新活动