Mysql 影响性能因素和性能优化

介绍

mysql作为中小型数据库,免费,开源等,受到中小型公司和用户的青睐,在项目中数据库作为基石,承载了项目生产的数据,一个好的项目能否给用户带来好的体验,往往和数据库设计优化密不可分

影响性能因素

业务需求对性能的影响

不合理的需求
需求:一个论坛帖子总量的统计
附加要求:实时更新
1,初级阶段:SELECT COUNT(*)
2,新建一个表,在这个表中更新这个汇总数据(频率问题)
3,真正的问题在于,实时?创建一个统计表,隔一段时间统计一次并存入;

没有用功能堆积
1.无用的数据库列堆积
2.错误的表设计
3.无用表关联
4.不合理字段长度
5.不合理类型添加索引

不合理的业务表设计
如一个文章列表需展示点赞和评论数的总数
有三个表 文章表 点赞表 评论表
撰写文章列表查询SQL,为了统计点赞数和评论数,使用到了两个子查询来统计评论总数和点赞总数

文章列表肯定读大于写,为了统计点赞数和评论数使用子查询,且性能慢,表设计不合理
我们在文章表完全可以加两个字段 点赞数和评论数,每次点赞和评论都进行修改,这样查询就不需要使用到子查询了

系统架构和业务实现的性能影响

不适合放数据中的数据
1.文档的二进制数据
2.流水队列数据
3.超大文本数据(如文章)

合理的使用缓存cache
1.系统配置信息
2.活跃用户的基本信息
3.活跃用户的定制化信息
4.基于时间的报表统计数据

减少数据库交互次数
1,N+1问题的解决:
1,使用链接查询;
2,使用1+1查询;

重复执行相同的SQL
在一个页面中,有相同内容,但是使用2条SQL去查询;

其他常见系统架构和实现问题
1、Cache 系统的不合理利用导致Cache 命中率低下造成数据库访问量的增加,同时也浪费了Cache系统的硬件资源投入;
2、过度依赖面向对象思想,对系统可扩展性的过渡追求,促使系统设计的时候将对象拆得过于离散,造成系统中大量的复杂Join语句,而MySQL Server 在各数据库系统中的主要优势在于处理简单逻辑的查询,这与其锁定的机制也有较大关系;
4、对数据库的过渡依赖,将大量更适合存放于文件系统中的数据存入了数据库中,造成数据库资源的浪费,影响到系统的整体性能,如各种日志信息;
5、过度理想化系统的用户体验,使大量非核心业务消耗过多的资源,如大量不需要实时更新的数据做了实时统计计算。

SQL引起性能原因

SQL执行过程
在这里插入图片描述

1.客户端发送一条查询给服务器
2.服务器首先去缓存中命中,命中就返回结果集,没有命中就执行下一步
3.服务器端通过解析器对sql进行解析,查看sql是否有语法错误,并生成一个解析树
4.预处理器检测解析树里面的语法,表,字段,是否存在,并在生成一个解析树
5.解析树再由优化器根据SQL所涉及到的数据表的统计信息进行计算,生成对应的执行计划
6.Mysql 通过执行引擎调 存储引擎的API.来执行优化器生成的执行计划
7.将结果集数据返回给客户端

SQL执行最大瓶颈在于磁盘IO,即数据读取,不同的SQL写法,所生成的执行计划不同,执行计划不同即在查询所产生的IO数量 完全不一样的数量级,从而照成性能差别

硬件环境对性能影响

1,提高IO指标
IOPS:每秒可提供的IO 访问次数;
IO 吞吐量:每秒的IO 总流量;
2,提高CPU计算能力;
3,如果是单独的数据库服务器,提高网络能力;

SQL优化

合理使用索引

MySQL中索引类型

1,B-TREE:使用平衡树实现索引,是mysql中使用最多的索引类型;在innodb中,存在两种索引类型,第一种是主键索引(primary key),在索引内容中直接保存数据的地址;第二种是其他索引,在索引内容中保存的是指向主键索引的引用;所以在使用innodb的时候,要尽量的使用主键索引,速度非常快;
2,Hash:把索引的值做hash运算,并存放到hash表中,使用较少,一般是memory引擎使用;因为使用hash表存储,按照常理,hash的性能比B-TREE效率高很多。
hash索引的缺点:

  1. hash索引只能适用于精确的值比较,=,in,或者<>;
  2. 无法使用索引排序;
  3. 组合hash索引无法使用部分索引;
  4. 如果大量索引hash值相同,性能较低;

3,full-text索引:全文检索索引,效率低,限制多
4,R-TREE:针对空间数据索引,使用很少

索引的利弊

1.索引的好处:

  1. 提高表数据的检索效率;
  2. 如果排序的列是索引列,大大降低排序成本;
  3. 在分组操作中如果分组条件是索引列,也会提高效率;

2.索引的问题:
4. 索引需要额外的维护成本;
5. 新增修改数据性能变慢

如何创建索引

  1. 较频繁的作为查询条件的字段应该创建索引;
  2. 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件;
  3. 更新非常频繁的字段不适合创建索引;
  4. 不会出现在WHERE 子句中的字段不该创建索引;

MySQL中索引使用限制

  1. BLOB 和TEXT 类型的列只能创建前缀索引
  2. MySQL 目前不支持函数索引
  3. 使用不等于(!= 或者<>)的时候MySQL 无法使用索引
  4. 过滤字段使用了函数运算后(如abs(column)),MySQL 无法使用索引
  5. Join 语句中Join 条件字段类型不一致的时候MySQL 无法使用索引
  6. 使用LIKE 操作的时候如果条件以通配符开始( ‘%abc…’)MySQL 无法使用索引
  7. 使用非等值查询的时候MySQL 无法使用Hash 索引

Explain关键字

Explain可以让我们查看MYSQL执行一条SQL所选择的执行计划;

使用方式:
explain SQL
在这里插入图片描述

返回结果字段意思:

  1. ID:执行查询的序列号;
  2. select_type:使用的查询类型
    1. DEPENDENT SUBQUERY:子查询中内层的第一个SELECT,依赖于外部查询的结果集;
    2. DEPENDENT UNION:子查询中的UNION,且为UNION 中从第二个SELECT 开始的后面所有SELECT,同样依赖于外部查询的结果集;
    3. PRIMARY:子查询中的最外层查询,注意并不是主键查询;
    4. SIMPLE:除子查询或者UNION 之外的其他查询;
    5. SUBQUERY:子查询内层查询的第一个SELECT,结果不依赖于外部查询结果集;
    6. UNCACHEABLE SUBQUERY:结果集无法缓存的子查询;
    7. UNION:UNION 语句中第二个SELECT 开始的后面所有SELECT,第一个SELECT 为PRIMARY
    8. UNION RESULT:UNION 中的合并结果;
  3. table:这次查询访问的数据表;
  4. type:对表所使用的访问方式:
    1. all:全表扫描
    2. const:读常量,且最多只会有一条记录匹配,由于是常量,所以实际上只需要读一次;
    3. eq_ref:最多只会有一条匹配结果,一般是通过主键或者唯一键索引来访问;
    4. fulltext:全文检索,针对full text索引列;
    5. index:全索引扫描;
    6. index_merge:查询中同时使用两个(或更多)索引,然后对索引结果进行merge 之后再读取表数据;
    7. index_subquery:子查询中的返回结果字段组合是一个索引(或索引组合),但不是一个主键或者唯一索引;
    8. rang:索引范围扫描;
    9. ref:Join 语句中被驱动表索引引用查询;
    10. ref_or_null:与ref 的唯一区别就是在使用索引引用查询之外再增加一个空值的查询;
    11. system:系统表,表中只有一行数据;
    12. unique_subquery:子查询中的返回结果字段组合是主键或者唯一约束;
  5. possible_keys:可选的索引;如果没有使用索引,为null;
  6. key:最终选择的索引;
  7. key_len:被选择的索引长度;
  8. ref:过滤的方式,比如const(常量),column(join),func(某个函数);
  9. rows:查询优化器通过收集到的统计信息估算出的查询条数;

优化JOIN

理解JOIN原理
mysql中使用Nested Loop Join来实现join;
A JOIN B:通过A表的结果集作为循环基础,一条一条的通过结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果;

join优化原则
1,尽可能减少Join 语句中的Nested Loop 的循环总次数,用小结果集驱动大结果集;
2,优先优化Nested Loop 的内层循环;
3,保证Join 语句中被驱动表上Join 条件字段已经被索引;
4,扩大join buffer的大小;

SQL优化原则

选择需要优化的SQL
1:优先优化高并发低消耗的SQL;

  1. 小时请求1W次,1次10个IO;
  2. 1小时请求10次,1次1W个IO;
  3. 从IO消耗,优化难度,CPU消耗进行比较;

2:定位性能瓶颈;

  1. SQL运行较慢有两个影响原因,IO和CPU,明确性能瓶颈所在;
  2. 明确优化目标;
  3. 任何SQL的优化,都从Explain语句开始;Explain语句能够得到数据库执行该SQL选择的执行计划;

使用最小Columns
1,特别是需要使用column排序的时候;
2,减少网络传输数据量;
3,MYSQL排序原理,是把所有的column数据全部取出,在排序缓存区排序,再返回结果;如果column数据量大,排序区容量不够的时候,就会使用先column排序,再取数据,再返回的多次请求方式;

使用最有效的过滤条件
1,过多的WHERE条件不一定能够提高访问性能;
2,一定要让where条件使用自己预期的执行计划;

避免复杂的JOIN和子查询
1,复杂的JOIN和子查询,需要锁定过多的资源,MYSQL在大量并发情况下处理锁定性能下降较快;
2,不要过多依赖SQL的功能,把复杂的SQL拆分为简单的SQL;
3,MySQL子查询性能较低,应尽量避免使用;

事务优化

隔离级别优化

  1. innodb实现了READ UNCOMMITTED/READ COMMITTED/REPEATABLE READ/SERIALIZABLE四种隔离级别;
    Abstract

  2. 默认使用REPEATABLE READ隔离级别;

  3. 可以通过SELECT @@tx_isolation;查看当前的事务隔离级别;

  4. 可以通过set tx_isolation=‘read-committed’;来修改默认的事务隔离级别;

事务日志优化

  1. 理解Innodb事务机制:
    1. 事务在buffer中对数据进行修改;
    2. 事务的变化记录在事务日志中;
    3. 在合适的时机同步事务日志中的数据到数据库中;
  2. 所以什么时候提交事务日志文件,对系统性能影响较大,可以通过设置innodb_flush_log_at_trx_commit来修改事务日志同步时机:
    1. innodb_flush_log_at_trx_commit = 0,每1秒钟同步一次事务日志文件;
    2. innodb_flush_log_at_trx_commit = 1,默认设置,每一个事务完成之后,同步一次事务日志文件;
    3. innodb_flush_log_at_trx_commit = 2,事务完成之后,写到事务日志文件中,等到日志覆盖再同步数据;

注意,1性能最差,2不能完全保证数据是写到数据文件中,如果宕机,可能会有数据丢失现象,但性能最高;1,性能和安全性居中;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值