[MySQL] 02- Optimisation solutions

前言


1、资源

MySQL 对于千万级的大表要怎么优化? - MySQL - 知乎【方法论】html

MySQL大表优化方案【一些优化的细节操做】mysql

MySQL大表优化方案【一些优化的细节操做】redis

分布式数据库下子查询和join等复杂sql如何实现?【分布式数据库相关】sql

 

2、将来计划

本篇内容只是大纲,将来对本文中提到的细节还需一一实践并总结。mongodb

哪一种类型的业务不须要关系型数据库,NOSQL就能够?数据库

基于hadoop、spark构建OLAP系统,采用redis来作缓存,怎么搞?segmentfault

 

 

 

策略


1、基本六步骤

  1. sql and index
  2. memcached, redis
  3. 主从复制,读写分离
  4. MySQL分区表
  5. 垂直拆分(分布式)
  6. 水平切分

 

 

2、详情

MYSQL数据库 通常都是按照这个步骤去演化的,成本也是由低到高;缓存

第一优化,sql和索引服务器

第二加缓存,memcached,redis架构

第三以上都作了后,仍是慢,就作主从复制或主主复制,读写分离,能够在应用层作,效率高,也能够用三方工具,第三方工具推荐360的atlas,其它的要么效率不高,要么没人维护;

|-- Goto: MySQL主从复制(Master-Slave)实践【不错,结尾引用也不错】

第四若是以上都作了仍是慢,mysql自带分区表,先试试这个,对你的应用是透明的,无需更改代码,可是sql语句是须要针对分区表作优化的,sql条件中要带上分区条件的列,从而使查询定位到少许的分区上,不然就会扫描所有分区,另外分区表还有一些坑,在这里就很少说了;

第五若是以上都作了,那就先作垂直拆分,其实就是根据你模块的耦合度,将一个大的系统分为多个小的系统,也就是分布式系统

第六才是水平切分,针对数据量大的表,这一步最麻烦,最能考验技术水平,要选择一个合理的sharding key,为了有好的查询效率,表结构也要改动,作必定的冗余,应用也要改,sql中尽可能带sharding key,将数据定位到限定的表上去查,而不是扫描所有的表;

|-- Goto: 关于数据库的水平切分和垂直切分的一些概念

 

 

3、SQL优化

  • SQL优化很重要

有人也许要说第一步优化sql和索引这还用说吗?的确,你们都知道,可是不少状况下,这一步作的并不到位,甚至有的只作了根据sql去建索引,根本没对sql优化(中枪了没?),除了最简单的增删改查外,想实现一个查询,能够写出不少种查询语句,不一样的语句,根据你选择的引擎、表中数据的分布状况、索引状况、数据库优化策略、查询中的锁策略等因素,最终查询的效率相差很大;

  • 技术、业务层面优化

优化要从总体去考虑,有时你优化一条语句后,其它查询反而效率被下降了,因此要取一个平衡点;即便精通mysql的话,除了纯技术面优化,还要根据业务面去优化sql语句,这样才能达到最优效果;你敢说你的sql和索引已是最优了吗?

  • 数据库俩引擎比对

MYISAM 和 INNODB 是Mysql数据库提供的两种存储引擎。二者的优劣可谓是各有千秋。INNODB会支持一些关系数据库的高级功能,如事务功能和行级锁,MYISAM不支持。MYISAM的性能更优,占用的存储空间少。因此,选择何种存储引擎,视具体应用而定。

再说一下不一样引擎的优化,myisam读的效果好,写的效率差,这和它数据存储格式,索引的指针和锁的策略有关的,它的数据是顺序存储的(innodb数据存储方式是聚簇索引),他的索引btree上的节点是一个指向数据物理位置的指针,因此查找起来很快,(innodb索引节点存的则是数据的主键,因此须要根据主键二次查找);myisam锁是表锁,只有读读之间是并发的,写写之间和读写之间(读和插入之间是能够并发的,去设置concurrent_insert参数,按期执行表优化操做,更新操做就没有办法了)是串行的,因此写起来慢,而且默认的写优先级比读优先级高,高到写操做来了后,能够立刻插入到读操做前面去,若是批量写,会致使读请求饿死,因此要设置读写优先级或设置多少写操做后执行读操做的策略;myisam不要使用查询时间太长的sql,若是策略使用不当,也会致使写饿死,因此尽可能去拆分查询效率低的sql。

innodb通常都是行锁,这个通常指的是sql用到索引的时候,行锁是加在索引上的,不是加在数据记录上的,若是sql没有用到索引,仍然会锁定表,mysql的读写之间是能够并发的,普通的select是不须要锁的,当查询的记录遇到锁时,用的是一致性的非锁定快照读,也就是根据数据库隔离级别策略,会去读被锁定行的快照,其它更新或加锁读语句用的是当前读,读取原始行;由于普通读与写不冲突,因此innodb不会出现读写饿死的状况,又由于在使用索引的时候用的是行锁,锁的粒度小,竞争相同锁的状况就少,就增长了并发处理,因此并发读写的效率仍是很优秀的,问题在于索引查询后的根据主键的二次查找致使效率低;


ps:很奇怪,为什innodb的索引叶子节点存的是主键而不是像mysism同样存数据的物理地址指针吗?若是存的是物理地址指针不就不须要二次查找了吗,这也是我开始的疑惑,根据mysism和innodb数据存储方式的差别去想,你就会明白了,我就不费口舌了!因此innodb为了不二次查找可使用索引覆盖技术,没法使用索引覆盖的,再延伸一下就是基于索引覆盖实现延迟关联;不知道什么是索引覆盖的,建议你不管如何都要弄清楚它是怎么回事!尽你所能去优化你的sql吧!说它成本低,却又是一项费时费力的活,须要在技术与业务都熟悉的状况下,用心去优化才能作到最优,优化后的效果也是立竿见影的!  

 
 
 

设计


1、设计大表切入点

  • 十个切入点
提问:如何设计或优化千万级别的大表?
话题有点范,就只好简单说下该如何作,对于一个存储设计,必须考虑业务特色,收集的信息以下:
 
1 数据的容量 1-3年内会大概多少条数据,每条数据大概多少字节
2 数据项 是否有大字段,那些字段的值是否常常被更新
3 数据查询SQL条件 哪些数据项的列名称常常出如今WHERE、GROUP BY、ORDER BY子句中等
4 数据更新类SQL条件 有多少列常常出现UPDATE或DELETE 的WHERE子句中
5 SQL量的统计比 如:SELECT:UPDATE+DELETE:INSERT=多少?
6 执行量数量级 预计大表及相关联的SQL,天天总的执行量在何数量级?
7 表中的数据 更新为主的业务 仍是 查询为主的业务
8 什么架构 打算采用什么数据库物理服务器,以及数据库服务器架构?
9 并发如何 采用怎么的处理并发的策略
10 存储引擎 存储引擎选择InnoDB仍是MyISAM? 
 
  • 多利用内存

至于优化如果指建立好的表,不能变更表结构的话,那建议InnoDB引擎,多利用点内存,减轻磁盘IO负载,由于IO每每是数据库服务器的瓶颈。

  • 索引好,则优化SQL

另外对优化索引结构去解决性能问题的话,建议优先考虑修改类SQL语句,使他们更快些,不得已只靠索引组织结构的方式,固然此话前提是

索引已经建立的很是好,如果读为主,能够考虑打开query_cache, 以及调整一些参数值:sort_buffer_size, read_buffer_size, read_rnd_buffer_size, join_buffer_size 

 
 

2、实战

  • 故事背景
我如今的公司有三张表,是5亿的数据,天天张表天天的增量是100w,每张表大概在10个columns左右。
 
  • 策略效果

下面是一些相关测试和对比

(1) 首先看engine,在大数据量状况下,在没有作分区的状况下

mysiam比innodb在只读的状况下,效率要高13%左右

 

(2) 在作了partition以后,你能够去读一下mysql的官方文档,其实对于partition,专门是对myisam作的优化;对于innodb,全部的数据是存在ibdata里面的,因此即便你能够看到schema变了,其实没有本质的变化

在分区出于同一个physical disk下面的状况下,提高大概只有1%

在分区在不一样的physical disk下,我分到了三个不一样的disks下,提高大概在3%,其实所谓的吞吐量,由不少因素决定的,好比你的explain parition时候能够看到,record在那一个分区,若是每一个分区都有,其实本质上没有解决读的问题,这样只会提高写的效率。

另一个问题在于,分区,你怎么分,若是一张表,有三个column都是常常被用于作查询条件的,实际上是一件很悲惨的事情,由于你没有办法对全部的sql作针对性的分区,若是你只是如mysql官方文档上说的,只对时间作一个分区,并且你也只用时间查询的话,恭喜你

 

(3) 表主要用来读仍是写,其实这个问题是不充分的,应该这样问,你在写入的时候,同时并发的查询多么?个人问题还比较简单,由于mongodb的shredding支持不能,在crush以后,仍是回到mysql,因此在一般状况下,9am-9pm,写入的状况不少,这个时候我会作一个view,view是基于最近被插入或者常常被查询的,经过作view来分离读取,就是说写是在table上的,读在进行逻辑判断前是在view上操做的

 

(4) 作一些archive table,好比先对这些大表作不少已有的统计分析,而后经过已有的分析+增量来解决

 

(5) 若是你用mysiam,还有一个问题你要注意,若是你的.configure的时候,加了一个max index length参数的时候,当你的record数大于制定长度的时候,这个index会被disable

相关文章
相关标签/搜索