MySQL 性能优化(全面)
造成性能问题的原因
- 大量 QPS(每秒处理的查询量) 和 TPS(每秒处理的事务量)
- 大量并发(同一时间的请求的数量)和高CPU使用率
- 磁盘IO是最主要的原因,要使用更快的磁盘设备,不要在主库进行数据备份
- 网卡IO激增会使用户无法连接数据库,应该减少服务器的数量,建立分级缓存,做好网络规划,避免使用
select *
- 大表问题: 记录超过千万行或表数据超过10G, 引起慢查询,引起DDL操作延迟甚至锁表,可以用分库分表或归档历史数据的方式解决
- 大事务问题: 运行时间比较长,操作的数据比较多的事务, 锁定太多的数据,造成大量的阻塞和锁超时,回滚时所需时间比较大,容易造成主从延迟
数据库结构设计
范式与反范式
范式:
- 1NF: 数据库表中的所有字段都只具有单一属性, 每个属性都不可再分
- 2NF: 要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言), 在 1NF 的基础上消除非主属性对于码的部分函数依赖
- 3NF: 确保数据表中的每一列数据都和主键直接相关,而不能间接相关
反范式
范式化的数据表设计,可以有效减少冗余,节省磁盘空间,但在实际应用中发现,如果严格按照范式设计表不利于数据库的读性能,而对大多数应用而言,都需要高效的读取数据.
范式化的设计在进行查询时要对多个表进行关联,且因为字段分布在不同的表中,也不能进行索引优化,所以数据表设计的难点是如果平衡处理空间和时间的矛盾,如果正确的进行反范式化设计以提高数据库的读性能
选择合适的存储引擎
存储引擎 | 事务 | 锁粒度 | 主要应用 | 忌用 | 其他 |
---|---|---|---|---|---|
MyISAM | 不支持 | 支持并发插入的表级锁 | 非事务型应用,只读类应用 | 读写操作频繁 | 支持数据压缩(myisampack) |
Innodb | 支持 | 行级锁 | 事务处理 | 无 | 建议开启独立表空间(innodb_file_per_table=1) |
Archive | 不支持 | 行级锁 | 日志记录,只支持insert, select | 需要随机读取,更新,删除 | 只支持在自增ID上增加索引 |
MRG_MYISAM | 不支持 | 表级锁 | 分段归档,数据仓库 | 全局查找过多的场景 | |
csv | 不支持 | 表级锁 | 做为数据交换的中间表 | 大多数应用 | 数据以cs文本格式存储在文件中,所有列不能为 NULL, 不支持索引 |
memory | 不支持 | 表级锁 | 用于查找或者是映射表,比如右边和地区的对应表,用于保存数据分析中的中间表,用于缓存周期性聚合数据的结果表 | 大多数应用 | 注意表中的数据丢失后无法恢复,所以所存的数据必须是可再次生成的 |
为字段选择合适的数据类型
当一个列可以选择多种数据类型时,应该优先选择数字类型,其次是日期或二进制类型,最后考虑字符类型.对于相级别的数据类型,应该优先选择占用空间小的数据类型
列出一些注意点:
- 整数类型根据取值范围合理的选择数据类型,可以节省很大空间,每种整数类型的存储空间都不同
- 实数类型要注意是否需要非常精确,float和double不精确,decimal精确
- varchar只占用必要的存储空间,长度小于255,额外占用一个字节存长度,大于255,额外占用两个字节存长度,应使用符合需求的最小长度, 适用于最大长度比平均长度大很多的场景,且该字段很少被更新,使用了多字节字符集存储字符串
- char 类型是定长的,会删除末尾的空格,最大宽度为255, 适合存储所有长度近似的值
- 绝不使用字符串存储日期时间
- datetime类型与时区无关,占用8个字节, timestamp 类型依赖所指定的时区,占用4个字节, 用int存时间戳不如用timestamp
- timestamp在行数据修改时可以自动修改为当前时间
- date类型只占用3个字节,比字符串,datetime,int都小,且可以利用日期时间函数进行日期间的计算
整型数据大小和范围
整型 | 大小 | 范围(无符号 unsigned)
—|— | —
TINYINT | 1 字节 | (0,255)
SMALLINT | 2 字节 | (0,65535)
MEDIUMINT | 3 字节 | (0,16777215)
INT/INTEGER | 4 字节 | (0,4294967295)
BIGINT | 8 字节 | (0,18446744073709551615)
索引优化
sql语句优化
找到需要优化的sql语句
sql语句优化技巧
MySQL服务器参数优化
1 | /* 内存配置相关参数 详细说明 http://waterandair.top/mysql-memory-optimization.html */ |
服务器系统参数优化
内核相关参数 (/etc/sysctl.conf)
1 | /* 增加系统可接受请求的数量 */ |
增加资源限制 (/etc/security/limit.conf)
增加可打开文件数(文件描述符)的限制, 关于文件描述符的详细介绍
1 | * - nofile 65535 |
磁盘调度策略 (/sys/block/devname/queue/scheduler)
查看: cat /sys/block/sda/queue/scheduler
, 默认为 cfq
修改为deadline策略: echo deadline > /sys/block/sda/queue/scheduler
磁盘调度策略介绍
noop (电梯式调度策略)
noop 实现了一个 FIFO 队列,它像电梯的工作方式一样对 I/O 请求进行组织,当有一个新的请求到来时,它将请求合并到最近的请求之后,以此来保证请求同一介质.noop倾向饿死读而有利于写,因此noop对于闪存设备,RAM及嵌入式系统是最好的选择
deadline (截止时间调度策略, 数据库类应用最好的选择)
deadline 确保了在一个截止时间内服务请求,这个截止时间是可调整的,而默认读期限短于写期限,这样就防止了写操作因为不能被读取而饿死的现象.
分布式架构优化
MySQL 复制
表分区
服务器硬件优化
选择 CPU
在选择CPU前,要明确程序是计算密集型还是IO密集型,如果是计算密集型,就要选择频率更高的CPU,如果是IO密集型,就要选择核心数量更多的CPU.因为MySQL不支持对同一 sql 的并发处理, 所以多核的 CPU 对于 sql 执行速度并没有帮助.但是MySQL的应用一般会要求并发量要高,CPU核心数越多,并发能力就越强 ,所以在资金有限的情况下,优先选择核心数量更多的CPU
选择内存
把数据缓存到内存中可以提高 MySQL 的性能, 常用的 MySQL 引擎中, MyISAM将索引缓存到内存中,数据通过操作系统进行缓存;InnoDB 中会同时在内存中缓存索引和数据.选择内存时,应该选择主板支持额最大内存频率,尽量购买相同品牌,颗粒,频率,电压,校验技术和型号的内存,尽可能买大内存
配置和选择磁盘
使用传统机器硬盘
最常见,使用最多,价格低,存储空间大,读写慢
选择传统硬盘主要考虑以下几个因素:
- 存储容量
- 传输速度
- 访问时间
- 主轴转速
- 物理尺寸(同等条件下,尺寸越小越好)
传统硬盘读取过程(2用的时间称为访问时间,3的过程称为传输速度):
- 移动磁头到磁盘表面上正确的位置
- 等待磁盘旋转,使所需的数据在磁头之下
- 等待磁盘旋转过去,所有所需的数据都被磁头读出
使用 RAID 增强传统机硬盘的性能
RAID, 是磁盘冗余队列的简称,RAID的作用就是可以把多个容量较小的磁盘组成一组容量更大的磁盘,并提供数据冗余来保证数据完成性
RAID 级别:
- RAID0 :又称数据条带,是最简单的一种形式,只需要2块以上的硬盘,成本最低,但没有冗余和错误修复能力
- RAID1: 又称磁盘镜像,在写入一块磁盘的同时,会在另一块闲置的磁盘生成镜像文件,在不影响性能的前提下最大限度的保证系统的可靠性和可修复性
- RAID5: 又称分布式奇偶校验磁盘阵列,通过分布式奇偶校验块,把数据分散到多个磁盘上,这样如果一个盘数据失效,都可以从奇偶校验块中重建.适合用以读操作为主的场景.最好用在从服务器上.
- RAID10(最常用): 由称分片的镜像,对磁盘先做 RAID1 之后对两组 RAID1 的磁盘再做 RAID0,所以读写都有良好的性能,相对于 RAID5 更简单,速度也更快
等级 | 特点 | 是否冗余 | 盘数 | 读 | 写
—|— | — | — | — | — | —
RAID0 | 便宜, 快速,危险| 否 | N | 快 | 快
RAID1 | 高速读,简单,安全| 是 | 2 | 快 | 慢
RAID5 | 安全,成本折中| 是 | N + 1 | 快 | 取决于最慢的盘
RAID10 | 贵,高速,安全| 有 | 2N | 快 | 快
使用固态硬盘 SSD 和 PCIe 卡
相比机械硬盘,固态硬盘有更好的随机读写性能,能更好的支持并发,但更容易损坏,适用于存在大量随机 I/O 的场景, 用于解决单线程负载的 IO 瓶颈
类别 | 特点 |
---|---|
SSD | 使用 SATA 接口,可以替换传统磁盘而不需任何改变,且支持 RAID 技术 |
PCIe卡 | 无法使用 SATA 接口,需要独特的驱动和配置,价格更贵,性能更好 |
文章标题:MySQL 性能优化(全面)
文章字数:3.9k
本文作者:Waterandair
发布时间:2018-08-26, 09:24:06
最后更新:2019-12-28, 14:03:59
原始链接:https://waterandair.github.io/2018-08-26-mysql-optimization.html版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。