「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」
MySQL 中的 processlist 可以展示 MySQL 中有哪些线程在运行。
在 MySQL 中执行下述命令,得到的结果如下图所示:
show full processlist;
上图中的各列名及其取值如下所示:
id:线程标志,系统分配的connection_id,可以使用select connection_id()查看,出问题也是用 kill + id 去杀线程,使用mysql > kill id;;User:显示当前用户,如果当前不是用root查询,这个命令只显示用户权限范围的sql语句;Host:该语句是来源,即从哪个IP和端口访问的;db:显示当前进程连接的数据库Command:执行的命令类型,一般是休眠(sleep),查询(query),连接(connect);Time:SQL语句持续的时间,单位是秒;State:语句执行状态,有copying to tmp table,Sorting result,Sending data等状态;info:显示执行的 SQL 语句;
State 列的状态
Checking table:检查表;Closing tables:将表中修改的数据刷新(Flush)到磁盘中,同时关闭已经用完的表;Copying to tmp table on disk:内存存储转换为硬盘存储;Creating tmp table:创建临时表;deleting from main table:多表删除中的第一步;deleting from reference tables:多表删除中的第二步;Flushing tables:FLUSH TABLES,等待其他线程关闭数据表Locked:查询有锁;Sending data:正在执行 SELECT 查询,然后把结果发送给客户端;Sorting for group:正在为分组排序;Sorting for order:正在排序
show processlist 显示的查询结果来自 information_schema 中的 processlist 表,可以用下述查询代替:
select * from information_schema.processlist
细节的内容可以通过 官方手册 查询学习。
本篇博客主要优化 MySQL 中的插入操作,核心实现 insert 优化任务。
load data infile 导入数据
使用上述命令,可以大幅度提高批量插入数据。
如果希望使用该命令,可以用 show 命令进行测试
show variables like '%infile%'
使用批量插入 如果希望一次性插入多条数据,可以使用一条 insert 语句,然后拼接多行数据。
insert into 表名 values(...),(...),(...)
禁用唯一检查 在插入数据时,可以临时取消唯一性校验,具体办法是在插入前执行下述命令
set unique_checks = 0
插入完毕之后在打开
set unique_checks = 1
禁用外键检查 与上述逻辑一致,相关命令如下所示。
set foreign_key_checks = 0
set foreign_key_checks = 1
禁止自动提交 禁止事务自动提交
set autocommit = 0
set autocommit = 1
禁用索引 临时性关闭索引
alter table 表名 disable keys
执行完毕打开索引
alter table 表名 enable keys
从配置的角度进行修改
bulk_insert_buffer_size 缓存大小,默认 8M,可以提高。
show variables like 'bulk_insert%'
这个参数只能对
MyISAM 使用,innodb 无效。
max_allowed_packet 接受的数据包大小,默认为 16M,可以提高
show variables like 'max_all%'
net_buffer_length 通信时缓存数据的大小,最小4k,最大16M,默认是1M。
show variables like 'net_buffer_length'
其它可学习内容
尽量在事务中进行插入操作
MySQL 默认每次进行 insert 操作时,都会创建一个事务,所以我们提前将批量插入操作放置到事务中,可以提高效率。
START TRANSACTION;
insert into 表名 values(...),(...),(...);
insert into 表名 values(...),(...),(...);
insert into 表名 values(...),(...),(...);
COMMIT;