文章目录
一、说一下MySQL性能优化
关于MySQL的性能优化,可以从SQL和索引优化、设计优化、配置优化、硬件优化等维度来分析。
首先是SQL和索引优化,这部分优化的成本最低,一般80%的问题都可以通过SQL和索引优化。
1、避免使用“SELECT *;”,只获取需要的字段,减少网络传输和内存消耗,并且如果能走覆盖索引不用回表的话性能也会有很大提高。
2、善用EXPLAIN分析,在定位到一个慢SQL后,使用EXPLAIN查看SQL的执行计划,重点关注type、possible_keys和key、rows及Extra列。
- type列:表示表的访问方式,即MySQL决定如何查找表中的行。它是判断查询效率至关重要的一个指标。
- system & const:最优级别,通过主键或者唯一索引定位到唯一行。
- eq_ref:多表关联时,使用主键或唯一索引关联
- ref:使用普通非唯一索引惊醒等值查询
- range:使用索引进行范围查询
- index:全索引扫描,比全表扫描稍好,一般是查询联合索引数据或者按照主键排序。
- 查询联合索引:select index_field1, index_field2, index_field3 from table
- 按照主键排序:select * from table order by id
- ALL:全表扫描,没有用到索引,这种情况一般就要优化。
- possible_keys和key:可能用到的索引和实际用到的索引
- rows:扫描行数
- Extra列:
3、索引创建 - 可以为
WHERE
、ORDERBY
、GROUPBY
子句中的字段建立联合索引,并注意顺序; - 创建索引的列选择区分度高的,区分度越高,索引效率越好;
4、索引使用 - 在使用索引时,尽量走覆盖索引,减少回表
- 要防止索引失效,
- 使用like左模糊匹配
- 对字段进行函数操作或者运算
- 不符合最左匹配原则
- 使用范围查询,会导致联合索引的后续索引字段无效,但是会有一个索引下推的逻辑
- 使用类型隐式转换,类型字符串使用数字查询会索引失效,但是类型数字使用字符串查询不会索引失效;
- 使用!=、<>、NOT IN、NOT LIKE等否定条件时
- 使用OR操作符连接不同的索引列,可以换成分别查询然后使用UNION合并
- 查询的数据占表中数据的比例较大;使用索引查询涉及两个步骤:先通过索引找到满足条件的记录ID,再通过这些ID获取完整记录(回表操作)。当结果集较大时,这种"随机IO"的成本可能高于顺序读取全表的成本,因此优化器会选择全表扫描。
- 索引字段的数据重复度过高,或者说区分度低
- ORDER BY或GROUP BY子句的使用不当
设计优化,良好的设计是高性能的基石。
- 选择合适的数据类型,在满足业务的前提下,选择尽可能小的数据类型,例如,用
TINYINT
代替INT
存储状态,VARCHAR长度够用就可以,尽量少用text,有必要可以通过给text的类型创建一张表,主表只保存text表的ID - 平衡范式与反范式,必要时可以通过反范式设计,通过增加冗余字段来避免复杂的
JOIN
,以空间换时间。 - 分库分表:包括垂直分库(按业务模块拆分)、垂直分表(将一张宽表按字段热度拆分)、水平分表(Sharding,将数据按某种规则分散到多个结构相同的表中)。
- 预聚合表:提前对数据进行初步的聚合,减少数据条数,例如销量表,可以预聚合一个月表。
- 引入缓存:使用Redis等缓存热点数据,减轻数据库压力。但是需要注意缓存与数据库的一致性问题。
系统配置
- 调整innodb_buffer_pool_size,加大buffer_pool的大小
- 调整刷盘策略,一般默认binlog和redoLog缓存是事务提交后就刷盘,可以修改成刷到page_cache,但是会牺牲一些安全性,在服务器宕机时可能会丢失数据