浅谈MySQL优化

关于MySQL数据库的优化

我认为可以从五个方面来讲:数据库设计层面的优化、SQL语句的优化、使用索引、使用集群实现主从复制和读写分离、水平垂直分库分表。

一、数据库设计层面的优化

字段的设计

尽量使用整型表示字符串,尽可能选择小的数据类型和指定短的长度,尽可能使用not null,非null的字段处理要比null字段的处理更加高效,而且不需要判断是否为null,null在MySQL中不好处理,存储需要额外空间。

是否遵循三大范式

根据实际情况决定我们设计的表是否遵循三大范式。

范式

(1)第一范式1NF:字段原子性
字段原子性,字段不可再分割。

(2)第二范式:消除对主键的部分依赖
对主键的部分依赖:某个字段依赖复合主键中的一部分。
解决方案:新增一个独立字段作为主键。

(3)第三范式:消除对主键的传递依赖

选择合适的存储引擎

然后就是选择合适的存储引擎,因为MyISAM相对简单所以在效率上要优于InnoDB.如果系统读多,写少。对原子性要求低。那么MyISAM最好的选择。且MyISAM恢复速度快。可直接用备份覆盖恢复。如果系统读少,写多的时候,尤其是并发写入高的时候。InnoDB就是首选了。

二、SQL语句的优化

这里只举几个简单的例子:
1.尽量避免较大的Offset,假如查询limit 10000,10,相当于对已查询出来的行数弃掉前10000行后再取10行,完全可以加一些条件过滤一下(完成筛选),而不应该使用limit跳过已查询到的数据。这是一个offset做无用功的问题。对应实际工程中,要避免出现大页码的情况,尽量引导用户做条件过滤。
2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描。
3.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。
4.尽量用Exists来代替in,not exists代替not in

三、索引

当符合以下情况之一时,可以创建索引
1.当表中的某些字段被频繁的作为查询条件时,可以在该字段上创建索引。
2.查询中排序、统计或者分组的字段,可以建立索引。
3.主键自动创建主键索引。
但也有一些情况不适合创建索引
1.频繁更新的字段不适合创建索引,因为每次更新不单单是更新记录,还会更新索引,保存索引文件
2.表记录太少,不需要创建索引;
3.经常增删改的表;
4.数据重复且分布平均的字段。注意某些数据包含大量重复数据,因此他建立索引就没有太大的效果,例如性别字段,只有男女,不适合建立索引。

索引失效的情况列举如下图所示

浅谈MySQL优化

四、集群

使用Redis部署集群实现主从复制和读写分离,以及数据的持久化操作。Redis的数据持久化策略包括RDB和AOF。

五、分库分表

使用MyCat实现分库分表。

垂直分表

垂直分表是基于数据库中的"列"进行,某个表字段较多,可以新建一张扩展表,将不经常用或字段长度较大的字段拆分出去到扩展表中。在字段很多的情况下(例如一个大表有100多个字段),通过"大表拆小表",更便于开发与维护,也能避免跨页问题(MySQL底层是通过数据页存储的,一条记录占用空间过大会导致跨页,造成额外的性能开销)。另外数据库以行为单位将数据加载到内存中,这样表中字段长度较短且访问频率较高,内存能加载更多的数据,命中率更高,减少了磁盘IO,从而提升了数据库性能。

垂直分库

垂直分库就是根据业务耦合性,将关联度低的不同表存储在不同的数据库。做法与大系统拆分为多个小系统类似,按业务分类进行独立划分。

水平(横向)切分

当一个应用难以再细粒度的垂直切分,或切分后数据量行数巨大,存在单库读写、存储性能瓶颈,这时候就需要进行水平切分了。
水平切分分为库内分表分库分表,是根据表内数据内在的逻辑关系,将同一个表按不同的条件分散到多个数据库或多个表中,每个表中只包含一部分数据,从而使得单个表的数据量变小,达到分布式的效果。
库内分表只解决了单一表数据量过大的问题,但没有将表分布到不同机器的库上,因此对于减轻MySQL数据库的压力来说,帮助不是很大,大家还是竞争同一个物理机的CPU、内存、网络IO,最好通过分库分表来解决。

参考文章:

面试题:你对mysql优化了解多少?