MySQL 被动性能优化
所以我们本文会重点介绍 MySQL 被动性能优化的知识,根据被动性能优化的知识,你就可以得到预防性能问题发生的一些方法,从而规避 MySQL 的性能问题。
本文我们会从问题入手,然后考虑这个问题产生的原因以及相应的优化方案。我们在实际开发中,通常会遇到以下 3 个问题:
- 单条 SQL 运行慢;
- 部分 SQL 运行慢;
- 整个 SQL 运行慢。
问题 1:单条 SQL 运行慢
问题分析
造成单条 SQL 运行比较慢的常见原因有以下两个:
- 未正常创建或使用索引;
- 表中数据量太大。
解决方案 1:创建并正确使用索引
索引是一种能帮助 MySQL 提高查询效率的主要手段,因此一般情况下我们遇到的单条 SQL 性能问题,通常都是由于未创建或为正确使用索引而导致的,所以在遇到单条 SQL 运行比较慢的情况下,你首先要做的就是检查此表的索引是否正常创建。
如果表的索引已经创建了,接下来就要检查一下此 SQL 语句是否正常触发了索引查询,如果发生以下情况那么 MySQL 将不能正常的使用索引:
- 在 where 子句中使用 != 或者 <> 操作符,查询引用会放弃索引而进行全表扫描;
- 不能使用前导模糊查询,也就是 '%XX' 或 '%XX%',由于前导模糊不能利用索引的顺序,必须一个个去找,看是否满足条件,这样会导致全索引扫描或者全表扫描;
- 如果条件中有 or 即使其中有条件带索引也不会正常使用索引,要想使用 or 又想让索引生效,只能将 or 条件中的每个列都加上索引才能正常使用;
- 在 where 子句中对字段进行表达式操作。
因此你要尽量避免以上情况,除了正常使用索引之外,我们也可以使用以下技巧来优化索引的查询速度:
- 尽量使用主键查询,而非其他索引,因为主键查询不会触发回表查询;
- 查询语句尽可能简单,大语句拆小语句,减少锁时间;
- 尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型;
- 用 exists 替代 in 查询;
- 避免在索引列上使用 is null 和 is not null。
回表查询:普通索引查询到主键索引后,回到主键索引树搜索的过程,我们称为回表查询。
解决方案 2:数据拆分
当表中数据量太大时 SQL 的查询会比较慢,你可以考虑拆分表,让每张表的数据量变小,从而提高查询效率。
1.垂直拆分
指的是将表进行拆分,把一张列比较多的表拆分为多张表。比如,用户表中一些字段经常被访问,将这些字段放在一张表中,另外一些不常用的字段放在另一张表中,插入数据时,使用事务确保两张表的数据一致性。垂直拆分的原则:
- 把不常用的字段单独放在一张表;
- 把 text,blob 等大字段拆分出来放在附表中;
- 经常组合查询的列放在一张表中。
2.水平拆分
指的是将数据表行进行拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。通常情况下,我们使用取模的方式来进行表的拆分,比如,一张有 400W 的用户表 users,为提高其查询效率我们把其分成 4 张表 users1,users2,users3,users4,然后通过用户 ID 取模的方法,同时查询、更新、删除也是通过取模的方法来操作。
表的其他优化方案:
- 使用可以存下数据最小的数据类型;
- 使用简单的数据类型,int 要比 varchar 类型在 MySQL 处理简单;
- 尽量使用 tinyint、smallint、mediumint 作为整数类型而非 int;
- 尽可能使用 not null 定义字段,因为 null 占用 4 字节空间;
- 尽量少用 text 类型,非用不可时最好考虑分表;
- 尽量使用 timestamp,而非 datetime;
- 单表不要有太多字段,建议在 20 个字段以内。