MYSQL 性能优化

MYSQL性能优化总结:

1.选择合适的存储引擎:innoDB

除非你的数据表主要做只读或者全文索引,你应该默认选择:innoDB

2.数据表字段设计

a. 通常使用范式化设计,因为范式化通常会似的执行操作更快:

  • 第一范式(确保每列保持原子性)
  • 第二范式(确保表中的每列都和主键相关)
  • 第三范式(确保每列都和主键列直接相关,而不是间接相关)

但我们有时需要混同范式化和反范式化,比如一个更新频率低的字段可以冗余在表中,避免关联查询

b.单表字段不宜过多:建议最多30个以内

c.选择小而简单的合适数据类型,比如字符串类型的,固定长度使用char,非定长度使用varchar,并分配合适且足够的空间;需储存IP字段时选择UNSIGNED INT等

d.尽量将列设置成NOT NULL

e.尽量使用整型做主键,应该尽量避免字符串类型作为标识列,因为它们很消耗空间,并且通常比数字类型慢

f.字段给定默认值,不设为null

g.业务表拆分, 分为业务基本表和业务扩展表

h.不使用触发器

i.尽量避免使用游标,因为游标的效率较差

3.使用索引和索引的优化

一.使用索引为什么快?

  • 索引相对于数据本身,数据量小
  • 索引是有序的,可以快速确定数据位置
  • InnoDB的表示索引组织表,表数据的分布按照主键排序

就好比书的目录,想要找到某一个内容,直接看目录便可找到对应的页

二.索引的存储结构:B+tree和hash

一般选择B+tree

三.索引的类型

按作用分类:

  • 主键索引:一般是在建表的时候指定了主键,就会创建主键索引,具有唯一性,不允许空值
  • 唯一索引:不允许有重复的值,但允许有空值,速度比普通索引略快
  • 普通索引:最基本的索引,没有任何限制
  • 全文索引:用作全文搜索匹配,但基本用不上只能索引英文单词,而且操作代价大

按数据存储结构分类:聚簇索引和非聚簇索引

四.索引优化

  • 对于经常在where子句使用的列,设置索引,这样会加快查找速度
  • 索引不是越多越好,维护索引是需要成本的
  • 在连接字段上应该建立索引
  • 尽量选择区分度高的列作为索引
  • 几个字段经常同时以AND方式出现在Where子句中,可以建立复合索引,否则考虑单字段索引
  • 只要列中含有NULL值,最好不要在此列中设置索引
  • 尽量使用短索引,如果可以,应该制定一个前缀长度
  • 对于有多个列where或者order by子句的,应该建立复合索引

避免索引失效:

  • 尽量避免在 where 子句中对字段进行表达式操作和函数操作
  • like模糊查询,前缀%会导致索引失效:like ‘%市’
  • 避免在Where子句中使用!= 或 <>操作符
  • 避免在where子句中对字段进行NULL值判断,否则将导致引擎放弃使用索引而进行全表扫描
  • where子句中使用or时,or两边的列都建立了索引,则可以使用索引
  • 列的类型需要一致
  • 尽量不要使用not in

4.SQL优化

一.sql语句

  • 单条查询最后添加LIMIT1 ,停止全表扫描
  • 不用mysql内置的函数,因为内置函数不会建立查询缓存
  • 将非”索引”数据分离,比如将大篇文章分离存储,不影响其他自动查询
  • 不要使用select * from table,用具体的字段列表代替*,不要返回用不到的字段
  • 使用join on进行多表查询,不使用子查询,因为子查询会创建临时表,损耗性能
  • 避免使用having筛选数据,而是使用where
  • order by后面的字段建立索引,利用索引的有序性排序,避免外部排序
  • 用exists,not exists和in,not in相互替代
  • 多表连接时,尽量小表驱动大表,即小表join大表
  • 对于经常使用的查询,可以开启缓存

二.使用Explain分析sql查询语句,选择更好的索引和写出更优化的查询语句

三.开启慢日志,定期查看慢查询日志记录,定位慢查询的sql,进而优化代码

5.架构优化

  • 分库分表(垂直,水平)
    分库分表是有成本的
    任何分库分表的行为都会提升业务逻辑的复杂度,数据库除了承载数据的存储和访问外,协助业务更好地实现需求和逻辑也是其重要的工作之一。分库分表会带来数据的合并、查询、更新条件的分离,以及事物的分离等多种后果,业务实现的复杂度往往会翻倍或指数级上升。所以在分表分库之前,应先升级硬盘、内存、CPU、网络、版本、读写分离、负载均衡及SQL语句优化。
    垂直分表一般是将表中的列按照相关性拆分开
    水平分表是按照hash或者时间拆分出来不同的表,每张表的结构是一样的

  • 缓存
    mysql本身是有缓存机制的,如果开启了查询缓存,我们在查询的时候就会先去缓存查询,但此处的缓存不是指mysql本身的缓存,因为mysql缓存不能减少客户端对mysql的请求访问,因此我们可以在其他地方做缓存,本地或者redis都是很好的选择,合理加上这些缓存,能有效减轻mysql数据库压力。

  • 读写分离
    读写分离即对mysql数据库做集群,以扩展mysql的负载,适用于读操作占主要的场景。主服务器负责写,从服务器负责读(主也可以负责读)。
  • 主从复制
    主从复制是和上面读写分离配合使用的,用在从库同步主库的数据的时候。

6.配置优化

  • 数据库配置优化
    Linux系统中MySQl配置文件一般位于/etc/my.cnf
    常用配置参数:
    innodb_buffer_pool_size【用于配置Innodb的缓冲池,如果数据库中只有Innodb表,则推荐配置量为总内存的75%】
    innodb_buffer_pool_instances【MySQL5.5中新增参数,可以控制缓冲池的个数,默认情况下只有一个缓冲池】
    innodb_flush_log_at_trx_commit【关键参数,对innodb的IO影响很大。默认值为1,可以取0,1,2三个值,0最快,1最安全,2折中。一般建议设为2,但如果数据安全性要求比较高则使用默认值1】

  • 使用足够大的写入缓存 innodb_log_file_size
  • 操作系统配置优化
    网络方面的配置,要修改/etc/sysctl.conf文件
    增加tcp支持的队列数
    net.ipv4.tcp_max_syn_backlog = 65535
    减少断开连接时 ,资源回收
    net.ipv4.tcp_max_tw_buckets = 8000
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout = 10