MySQL单条INSERT...SELECT语句最多支持插入多少行查询数据?
关于INSERT...SELECT批量复制数据的问题解答
你当前使用的跨表复制语句:
INSERT INTO summary_table SELECT * FROM wallet_transaction WHERE type_id = 1;
在常规MySQL配置下,数十万行级别的数据量完全可以正常执行完成,不存在针对INSERT ... SELECT语法的单条语句固定最大插入行数硬限制。
核心规则说明
- 不要把
INSERT ... SELECT和拼接多组VALUES的多行INSERT语句混淆:后者是把所有待插入的行数据全部拼接在同一个请求数据包里发送给MySQL,直接受max_allowed_packet参数限制,数据包大小超过配置阈值就会直接报错;但INSERT ... SELECT的执行逻辑是从源表逐行/逐批读取符合条件的数据,再写入目标表,不需要把所有待插入数据一次性加载到请求包中,因此没有直接的行数上限。 - 这类语句的实际可承载数据量,只和以下因素相关:
- 目标表所在磁盘的剩余空间,需要容纳新插入的数据、索引以及binlog(若开启binlog)、redo日志等额外文件
- InnoDB引擎相关配置,比如缓冲池大小
innodb_buffer_pool_size、事务日志大小innodb_log_file_size,配置足够时可以大幅提升批量写入的效率 - 锁等待阈值,比如
innodb_lock_wait_timeout,如果执行期间源表、目标表有其他业务写入产生锁冲突,等待超过阈值会中断语句,和插入行数本身没有关系 - 服务器硬件资源,比如磁盘IO性能、内存余量,资源不足时可能导致执行过慢甚至超时中断
大批量数据复制的实操建议
- 先给源表
wallet_transaction的type_id字段加上索引,避免全表扫描,能大幅缩短查询时间,减少锁持有时长 - 如果后续符合条件的数据量增长到百万级以上,不建议单条语句一次性全量插入,避免长事务引发锁堆积、主从延迟问题,可以按主键范围分批写入,每次插入1万~10万行即可,参考写法:
INSERT INTO summary_table SELECT * FROM wallet_transaction WHERE type_id = 1 AND id BETWEEN 起始ID AND 结束ID;
- 尽量避开业务高峰期执行批量写入操作,减少对线上正常业务的影响
只要服务器资源充足、配置合理,
INSERT ... SELECT语句哪怕一次性插入千万级数据也可以执行完成,只是执行时间会随数据量增长相应变长。
内容的提问来源于stack exchange,提问作者Sagar Sangwan
相关产品推荐
相关产品推荐

