浅谈MySQL的优化

  平时在开发中大多在写业务逻辑,不多关注于底层sql的执行效率,大多能交给batis的mapper作的就交给它去作。mysql

  然而这些天愈来愈发现,你们仍是很愿意手写sql的,每每一段业务逻辑,能够用稍微复杂一些的sql直接查询到,避免了代码中屡次访问数据库(固然,我以为若是sql太过复杂也不是很好,也许性能更好,但对于逻辑的更改和扩展都是不小的负担,这个仍是要权衡一下),经过手写sql,能够提升一些查询性能也是不错的。linux

  今天在开发过程当中遇到了一个情景,对于多个团队id的一个Set传给Mysql(sql中用的in的方式)做为查询条件。以前仅仅用了tk-mybatis的Example的inAnd方法,后来想本身写一下看看性能如何,因而改了mapper中的sql,使用了in标签实现。sql

  可是在explain的时候发现,mysql竟然没有用到in的列所创建的索引,这就让我很迷惑了,印象中并无哪里说到过in可使索引失效的。数据库

  后来经过交流和测试才发现,原来是mysql底层作了优化,在他认为in中数据量不大,使用索引并不会带来更小开销的状况下,便不会使用索引。这一点其实仍是很智能的,我也想借此机会总结一下以前看到过,学习过的一些mysql优化知识,但愿平时能学以至用吧。缓存

一.优化的策略安全

1. 引擎选择(主要针对于MyISAM和InnoDB)
  • 首先是区别:
    MyISAM是非事务安全型的, 而InnoDB是事务安全型的。
    MyISAM锁的粒度是表级, 而InnoDB支持行级锁定。
    MyISAM支持全文类型索引, 而InnoDB不支持全文索引。
    MyISAM相对简单, 因此在效率上要优于InnoDB, 小型应用 能够考虑使用 MyISAM。
    MyISAM表是保存成文件的形式, 在跨平台的数据转移中 使用 MyISAM存储会省去很多的麻烦。
    InnoDB表比MyISAM表更安全, 能够在保证数据不会丢失的状况下, 切换非事务表到事务表(alter table tablename
    type=innodb) 。
  • 而后是使用场景:
    MyISAM管理非事务表。 它提供高速存储和检索, 以及全文搜索能力 。 若是应用 中 须要执行大量的SELECT查询, 那
    么MyISAM是更好的选择。
    InnoDB用 于事务处理应用 程序, 具备众多特性, 包括ACID事务支持。 若是应用 中 须要执行大量的INSERT或UPDATE操
    做, 则应该使用 InnoDB, 这样能够提升多用 户并发操做的性能。
2. 正确使用索引
  • 适合创建的:where子句,链接子句,order by,group by, distinct 后,不要再select列加。
  • 若是数据不多更新,而且查询字段很少,能够考虑索引覆盖。
  • 索引值应该不相同,惟一值时效果最好,大量重复效果不好
  • 使用短索引,指定前缀长度char(50)的前20,30值惟一例:文件名;索引缓存必定(小)时,存的索引多,消耗IO更小,能提升查找速度
  • 最左前缀n列索引,最左列的值匹配,更快。
  • like查询,索引会失效,尽可能少用like;or,计算操做,函数,数据类型转换等都会使索引失效。
  • 多用简单句,避免临时表过多。
  • 能用union all就不用union(union会多排序和去重的花销)
  • 索引自己占空间,而且维护代价高,不是越多越好。
3. 避免使用SELECT *
  • 返回结果过多,下降查询的速度
  • 过多的返回结果,会增大服务器返回给端的数据传输量。例:网络传输速度面,弱网络环境下,容易形成请求失效

2、其余硬件优化服务器

1. Linux内核用内存开缓存存放数据
  • 写文件:文件延迟写入机制,先把文件存放到缓存,达到必定程度写进硬盘
  • 读文件:同时读文件到缓存,下次须要相同文件直接从缓存中取,而不是从硬盘取
2. 增长应用缓存
  • 本地缓存:数据防盗服务器内存的文件中
  • 分布式缓存:Redis, Mencache 读写性能很是高,QPS(每秒查询请求数)每秒达到1W以上;数据持久化用Redis,不持久化二者均可以 

 

3、架构优化网络

 这个我听了一下EP的分享,也看到不少种架构模型,可是仍是因为本身经验太少,不少仍是听不太明白,总结一下看到过的方法吧:mysql优化

1. 分表
  • 水平拆分:数据分红多个表拆分后的每张表的表头相同mybatis

  • 垂直拆分:字段分红多个表

  • 插入数据、更新数据、删除数据、查询数据时:MyISAM MERGE存储引擎,多个表合成一个表 InnoDB用alter table,变成MyISAM存储引擎,而后MEGRE

  • 表更大的话就须要分库了

2. 读写分离
  • 读是一些机器,写是一些机器,二进制文件的主从复制,延迟解决方案。
  • 数据库压力大了,能够把读和写拆开,对应主从服务器,主服务器写操做、从服务器是读操做。
  • 主服务器写操做的同时,同步到从服务器,保持数据完整性——主从复制

  • 主从复制原理:基于主服务器的二进制日志(binlog)跟踪全部的对数据库的完整更改实现。要实现主从复制,必须在主服务器上启动二进制日志,主从复制是异步复制,三个线程参与:主服务器一个线程(IO线程)、从服务器两个(IO线程和SQL线程)

  • 主从复制过程:

  • a. 从数据库,执行start slave开启主从复制;

  • b. 从数据库IO线程会经过主数据库受权的用户请求链接主数据库,并请求主数据库的binlog日志的指定位置,change master命令指定日志文件位置

  • c. 主数据库收到IO请求,负责复制的IO线程跟据请求读取的指定binlog文件返回给从数据库的IO线程,返回的信息除了日志文件,还有本次返回的日志内容在binlog文件名称和位置

  • d. 从数据库获取的内容和位置(binlog),写入到(从数据库)relaylog中继日志的最末端,并将新的binlog文件名和位置记录到master-info文件,方便下次读取主数据库的binlog日志,指定位置,方便定位

  • e. 从数据库SQL线程,实时检测本地relaylog新增内容,解析为SQL语句,执行。

  • 弊端:延迟

  • 主从复制延迟解决方案:
  • a. 定位问题:延迟瓶颈,IO压力大,升级硬件,换成SSD
  • b. 单线程从relaylog执行MySQL语句延迟,换成MySQL5.6以上版本多线程,或者Tungsten第三方并行复制工具
  • c. 都不行,直接分库
3. 分库
  • 这一部分网上的资料也不少,可是因为本身确实经验缺少,先不作整理了。(如今以为,复制却不能消化的是没有意义的)

 

4、其余

  我能想到的就是:慢查询的记录(固然包括一些参数的设定);explain语句进行分析(分析出的结果表要详细了解每一列的含义);show profile查看每个小环节的性能消耗,能够定位到具体的一步。

 

写在最后:其实平时开发过程当中仍是应该多关注一下底层实现,虽然如今的开发框架不少,许多工具都帮咱们作了底层的封装和优化,可是咱们并不能所以丧失了这部分能力。如同咱们能够借助单车、汽车多样出行,但当堵车的时候,仍是要有徒步的能力。真正理解,才能作得更完善,我真的还有很长的路要走。

相关文章
相关标签/搜索