Linux-mysql-性能优化
压力测试工具
常见 MySQL 压力测试工具
- mysqlslap
- Sysbench:功能强大,官网: https://github.com/akopytov/sysbench
- tpcc-mysql
- MySQL Benchmark Suite
- MySQL super-smack
- MyBench
mysqlslap
mysqlslap:来自于mysql或mariadb包,测试的过程默认生成一个mysqlslap的schema,生成测试表 t1,查询和插入测试数据,mysqlslap库自动生成,如果已经存在则先删除。用--only-print来打印实际 的测试过程,整个测试完成后不会在数据库中留下痕迹
使用格式:
mysqlslap [options]
常用参数 [options] 说明:
--auto-generate-sql, -a #自动生成测试表和数据,表示用mysqlslap工具自己生成的SQL脚本来测试并发压力 --auto-generate-sql-load-type=type #测试语句的类型。代表要测试的环境是读操作还是写操作还是两者混合的。取值包括:read,key,write,update和mixed(默认) --auto-generate-sql-add-auto-increment #代表对生成的表自动添加auto_increment列,从5.1.18版本开始支持 --number-char-cols=N, -x N #自动生成的测试表中包含多少个字符类型的列,默认1 --number-int-cols=N, -y N #自动生成的测试表中包含多少个数字类型的列,默认1 --number-of-queries=N #总的测试查询次数(并发客户数×每客户查询次数) --query=name,-q #使用自定义脚本执行测试,例如可以调用自定义的存储过程或者sql语句来执行测试 --create-schema #代表自定义的测试库名称,测试的schema --commint=N #多少条DML后提交一次 --compress, -C #如服务器和客户端都支持压缩,则压缩信息 --concurrency=N, -c N #表示并发量,即模拟多少个客户端同时执行select。可指定多个值,以逗号或者--delimiter参数指定值做为分隔符,如:--concurrency=100,200,500 --engine=engine_name, -e engine_name #代表要测试的引擎,可以有多个,用分隔符隔开。例如:- -engines=myisam,innodb --iterations=N, -i N #测试执行的迭代次数,代表要在不同并发环境下,各自运行测试多少次 --only-print #只打印测试语句而不实际执行。 --detach=N #执行N条语句后断开重连 --debug-info, -T #打印内存和CPU的相关信息
mysqlslap示例
#单线程测试 mysqlslap -a -uroot -pmagedu #多线程测试。使用--concurrency来模拟并发连接 mysqlslap -a -c 100 -uroot -pmagedu #迭代测试。用于需要多次执行测试得到平均值 mysqlslap -a -i 10 -uroot -pmagedu mysqlslap ---auto-generate-sql-add-autoincrement -a mysqlslap -a --auto-generate-sql-load-type=read mysqlslap -a --auto-generate-secondary-indexes=3 mysqlslap -a --auto-generate-sql-write-number=1000 mysqlslap --create-schema world -q "select count(*) from City" mysqlslap -a -e innodb -uroot -pmagedu mysqlslap -a --number-of-queries=10 -uroot -pmagedu #测试同时不同的存储引擎的性能进行对比 mysqlslap -a --concurrency=50,100 --number-of-queries 1000 --iterations=5 -- engine=myisam,innodb --debug-info -uroot -pmagedu #执行一次测试,分别50和100个并发,执行1000次总查询 mysqlslap -a --concurrency=50,100 --number-of-queries 1000 --debug-info -uroot - pmagedu #50和100个并发分别得到一次测试结果(Benchmark),并发数越多,执行完所有查询的时间越长。为了准确 起见,可以多迭代测试几次 mysqlslap -a --concurrency=50,100 --number-of-queries 1000 --iterations=5 -- debug-info -uroot -pmagedu
生产环境 my.cnf 配置案例
参考硬件:内存 32G
#打开独立表空间 innodb_file_per_table = 1 #MySQL 服务所允许的同时会话数的上限,经常出现Too Many Connections的错误提示,则需要增大此值 max_connections = 8000 #所有线程所打开表的数量 open_files_limit = 10240 #back_log 是操作系统在监听队列中所能保持的连接数 back_log = 300 #每个客户端连接最大的错误允许数量,当超过该次数,MYSQL服务器将禁止此主机的连接请求,直到MYSQL服 务器重启或通过flush hosts命令清空此主机的相关信息 max_connect_errors = 1000 #每个连接传输数据大小.最大1G,须是1024的倍数,一般设为最大的BLOB的值 max_allowed_packet = 32M #指定一个请求的最大连接时间 wait_timeout = 10 # 排序缓冲被用来处理类似ORDER BY以及GROUP BY队列所引起的排序 sort_buffer_size = 16M #不带索引的全表扫描.使用的buffer的最小值 join_buffer_size = 16M #查询缓冲大小 query_cache_size = 128M #指定单个查询能够使用的缓冲区大小,缺省为1M query_cache_limit = 4M # 设定默认的事务隔离级别 transaction_isolation = REPEATABLE-READ # 线程使用的堆大小. 此值限制内存中能处理的存储过程的递归深度和SQL语句复杂性,此容量的内存在每次 连接时被预留. thread_stack = 512K # 二进制日志功能 log-bin=/data/mysqlbinlogs/ #二进制日志格式 binlog_format=row #InnoDB使用一个缓冲池来保存索引和原始数据, 可设置这个变量到物理内存大小的80% innodb_buffer_pool_size = 24G #用来同步IO操作的IO线程的数量 innodb_file_io_threads = 4 #在InnoDb核心内的允许线程数量,建议的设置是CPU数量加上磁盘数量的两倍 innodb_thread_concurrency = 16 # 用来缓冲日志数据的缓冲区的大小 innodb_log_buffer_size = 16M 在日志组中每个日志文件的大小 innodb_log_file_size = 512M # 在日志组中的文件总数 innodb_log_files_in_group = 3 # SQL语句在被回滚前,InnoDB事务等待InnoDB行锁的时间 innodb_lock_wait_timeout = 120 #慢查询时长 long_query_time = 2 #将没有使用索引的查询也记录下来 log-queries-not-using-indexes
MySQL配置最佳实践
高并发大数据的互联网业务,架构设计思路是"解放数据库CPU,将计算转移到服务层",并发量大的情 况下,这些功能很可能将数据库拖死,业务逻辑放到服务层具备更好的扩展性,能够轻易实现"增机器就 加性能"
参考资料: 阿里巴巴Java开发手册:https://developer.aliyun.com/topic/java2020 58到家数据库30条军规解读:http://zhuanlan.51cto.com/art/201702/531364.htm 以下规范适用场景:并发量大、数据量大的互联网业务
基础规范
- 必须使用InnoDB存储引擎
- 解读:支持事务、行级锁、并发性能更好、CPU及内存缓存页优化使得资源利用率更高
- 使用UTF8MB4字符集
- 解读:万国码,无需转码,无乱码风险,节省空间,支持表情包及生僻字
- 数据表、数据字段必须加入中文注释
- 解读:N年后谁知道这个r1,r2,r3字段是干嘛的
- 禁止使用存储过程、视图、触发器、Event
- 解读:高并发大数据的互联网业务,架构设计思路是"解放数据库CPU,将计算转移到服务层",并发量 大的情况下,这些功能很可能将数据库拖死,业务逻辑放到服务层具备更好的扩展性,能够轻易实现"增 机器就加性能"。数据库擅长存储与索引,CPU计算还是上移吧!
- 禁止存储大文件或者大照片
- 解读:为何要让数据库做它不擅长的事情?大文件和照片存储在文件系统,数据库里存URI多好。
命名规范
只允许使用内网域名,而不是ip连接数据库
线上环境、开发环境、测试环境数据库内网域名遵循命名规范
业务名称:xxx
线上环境:xxx.db
开发环境:xxx.rdb
测试环境:xxx.tdb
从库在名称后加-s标识,备库在名称后加-ss标识
线上从库:xxx-s.d
线上备库:xxx-sss.db
库名、表名、字段名:小写,下划线风格,不超过32个字符,必须见名知意,禁止拼音英文混用
库名与应用名称尽量一致,表名:t_业务名称_表的作用,主键名:pk_xxx,非唯一索引名:idx_xxx,唯 一键索引名:uk_xxx
表设计规范
必须把字段定义为NOT NULL并且提供默认值
解读: a)null的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化 b)null 这种类型MySQL内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较多空字段的时候,数据库的处理性能会降低很多 c)null值需要更多的存储空,无论是表还是索引中每行中的null的列都需要额外的空间来标识 d)对null 的处理时候,只能采用is null或is not null,而不能采用=、in、<、<>、!=、not in这些操作符号。如:where name!='shenjian',如果存在name为null值的记录,查询结果就不会包含name为null值的记录
禁止使用TEXT、BLOB类型
解读:会浪费更多的磁盘和内存空间,非必要的大量的大字段查询会淘汰掉热数据,导致内存命中率急剧降低,影响数据库性能
禁止使用小数存储货币
解读:使用整数吧,小数容易导致钱对不上
必须使用varchar(20)存储手机号
解读: a)涉及到区号或者国家代号,可能出现+-() b)手机号会去做数学运算么? c)varchar可以支持模糊查询,例如:like"138%"
禁止使用ENUM,可使用TINYINT代替
解读:
a)增加新的ENUM值要做DDL操作
b)ENUM的内部实际存储就是整数,你以为自己定义的是字符串?
索引设计规范
- 单表索引建议控制在5个以内
- 单索引字段数不允许超过5个
- 解读:字段超过5个时,实际已经起不到有效过滤数据的作用了
- 禁止在更新十分频繁、区分度不高的属性上建立索引
- 解读:a)更新会变更B+树,更新频繁的字段建立索引会大大降低数据库性能
- b)"性别"这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类 似
- 建立组合索引,必须把区分度高的字段放在前面
- 解读:能够更加有效的过滤数据
SQL使用规范
禁止使用SELECT *,只获取必要的字段,需要显示说明列属性
解读:
a)读取不需要的列会增加CPU、IO、NET消耗
b)不能有效的利用覆盖索引
c)使用SELECT *容易在增加或者删除字段后出现程序BUG
禁止使用INSERT INTO t_xxx VALUES(xxx),必须显示指定插入的列属性
解读:容易在增加或者删除字段后出现程序BUG
禁止使用属性隐式转换
解读:SELECT uid FROM t_user WHERE phone=13812345678 会导致全表扫描,而不能命中phone索引,猜猜为什么?(这个线上问题不止出现过一次)
禁止在WHERE条件的属性上使用函数或者表达式
解读:SELECT uid FROM t_user WHERE from_unixtime(day)>='2017-02-15' 会导致全表扫描 正确的写法是:SELECT uid FROM t_user WHERE day>= unix_timestamp('2017-02-15 00:00:00')
禁止负向查询,以及%开头的模糊查询
解读: a)负向查询条件:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,会导致全表扫描 b)%开头的模糊查询,会导致全表扫描
禁止大表使用JOIN查询,禁止大表使用子查询
解读:会产生临时表,消耗较多内存与CPU,极大影响数据库性能
禁止使用OR条件,必须改为IN查询
解读:旧版本Mysql的OR查询是不能命中索引的,即使能命中索引,为何要让数据库耗费更多的CPU帮助实施查询优化呢?
应用程序必须捕获SQL异常,并有相应处理
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)