MySQL 性能优化的那点事儿

1、MySQL的主要适用场景html

一、Web网站系统web

二、日志记录系统算法

三、数据仓库系统数据库

四、嵌入式系统缓存


2、MySQL架构图安全


94d17e5cb90b24e91c8c75e67e8877c3.jpeg


3、MySQL存储引擎概述性能优化


1)MyISAM存储引擎服务器


MyISAM存储引擎的表在数据库中,每个表都被存放为三个以表名命名的物理文件。首先确定会有任何存储引擎都不可缺乏的存放表结构定义信息的.frm文件,另外还有.MYD和.MYI文件,分别存放了表的数据(.MYD)和索引数据(.MYI)。每一个表都有且仅有这样三个文件作为MyISAM存储类型的表的存储,也就是说无论这个表有多少个索引,都是存放在同一个.MYI文件中。网络


MyISAM支持如下三种类型的索引:数据结构


一、B-Tree索引


B-Tree索引,顾名思义,就是全部的索引节点都按照balancetree的数据结构来存储,全部的索引数据节点都在叶节点。


二、R-Tree索引


R-Tree索引的存储方式和b-tree索引有一些区别,主要设计用于为存储空间和多维数据的字段作索引,因此目前的MySQL版原本说,也仅支持geometry类型的字段做索引。


三、Full-text索引


Full-text索引就是咱们长说的全文索引,他的存储结构也是b-tree。主要是为了解决在咱们须要用like查询的低效问题。


2)Innodb 存储引擎


一、支持事务安装

二、数据多版本读取

三、锁定机制的改进

四、实现外键


3)NDBCluster存储引擎


NDB存储引擎也叫NDBCluster存储引擎,主要用于MySQLCluster分布式集群环境,Cluster是MySQL从5.0版本才开始提供的新功能。


4)Merge存储引擎


MERGE存储引擎,在MySQL用户手册中也提到了,也被你们认识为MRG_MyISAM引擎。Why?由于MERGE存储引擎能够简单的理解为其功能就是实现了对结构相同的MyISAM表,经过一些特殊的包装对外提供一个单一的访问入口,以达到减少应用的复杂度的目的。要建立MERGE表,不只仅基表的结构要彻底一致,包括字段的顺序,基表的索引也必须彻底一致。


5)Memory存储引擎


Memory存储引擎,经过名字就很容易让人知道,他是一个将数据存储在内存中的存储引擎。Memory存储引擎不会将任何数据存放到磁盘上,仅仅存放了一个表结构相关信息的.frm文件在磁盘上面。因此一旦MySQLCrash或者主机Crash以后,Memory的表就只剩下一个结构了。Memory表支持索引,而且同时支持Hash和B-Tree两种格式的索引。因为是存放在内存中,因此Memory都是按照定长的空间来存储数据的,并且不支持BLOB和TEXT类型的字段。Memory存储引擎实现页级锁定。


6)BDB存储引擎


BDB存储引擎全称为BerkeleyDB存储引擎,和Innodb同样,也不是MySQL本身开发实现的一个存储引擎,而是由SleepycatSoftware所提供,固然,也是开源存储引擎,一样支持事务安全。


7)FEDERATED存储引擎


FEDERATED存储引擎所实现的功能,和Oracle的DBLINK基本类似,主要用来提供对远程MySQL服务器上面的数据的访问接口。若是咱们使用源码编译来安装MySQL,那么必须手工指定启用FEDERATED存储引擎才行,由于MySQL默认是不起用该存储引擎的。


8)ARCHIVE存储引擎


ARCHIVE存储引擎主要用于经过较小的存储空间来存放过时的不多访问的历史数据。ARCHIVE表不支持索引,经过一个.frm的结构定义文件,一个.ARZ的数据压缩文件还有一个.ARM的meta信息文件。因为其所存放的数据的特殊性,ARCHIVE表不支持删除,修改操


做,仅支持插入和查询操做。锁定机制为行级锁定。


9)BLACKHOLE存储引擎


BLACKHOLE存储引擎是一个很是有意思的存储引擎,功能恰如其名,就是一个“黑洞”。就像咱们unix系统下面的“/dev/null”设备同样,无论咱们写入任何信息,都是有去无回。


10)CSV存储引擎


CSV存储引擎实际上操做的就是一个标准的CSV文件,他不支持索引。起主要用途就是你们有些时候可能会须要经过数据库中的数据导出成一份报表文件,而CSV文件是不少软件都支持的一种较为标准的格式,因此咱们能够经过先在数据库中创建一张CVS表,而后将生成的报表信息插入到该表,便可获得一份CSV报表文件了。


4、影响MySQLServer性能的相关因素


1 商业需求对性能的影响


典型需求:一个论坛帖子总量的统计,要求:实时更新。


2 系统架构及实现对性能的影响


如下几类数据都是不适合在数据库中存放的:


二进制多媒体数据

流水队列数据

超大文本数据


经过Cache技术来提升系统性能:


系统各类配置及规则数据;

活跃用户的基本信息数据;

活跃用户的个性化定制信息数据;

准实时的统计信息数据;

其余一些访问频繁但变动较少的数据;


3 Query语句对系统性能的影响


需求:取出某个group(假设id为1)下的用户编号(id),用户昵称(nick_name),并按照加入组的时间(user_group.gmt_create)来进行倒序排列,取出前20个。


解决方案一:


SELECT id,nick_name FROM user,user_group WHERE user_group.group_id=1 and user_group.user_id=user.id ORDER BY user_group.gmt_create desc limit 100,20;


解决方案二:


SELECT user.id,user.nick_name FROM(SELECT user_idFROM user_groupWHERE user_group.group_id=1ORDER BY gmt_create desclimit 100,20)t,userWHERE t.user_id=user.id;


经过比较两个解决方案的执行计划,咱们能够看到第一中解决方案中须要和user表参与Join的记录数MySQL经过统计数据估算出来是31156,也就是经过user_group表返回的全部知足group_id=1的记录数(系统中的实际数据是20000)。而第二种解决方案的执行计划中,user表参与Join的数据就只有20条,二者相差很大,咱们认为第二中解决方案应该明显优于第一种解决方案。


4 Schema设计对系统的性能影响


尽可能减小对数据库访问的请求。

尽可能减小无用数据的查询请求。


5 硬件环境对系统性能的影响


一、典型OLTP应用系统


对于各类数据库系统环境中你们最多见的OLTP系统,其特色是并发量大,总体数据量比较多,但每次访问的数据比较少,且访问的数据比较离散,活跃数据占整体数据的比例不是太大。对于这类系统的数据库其实是最难维护,最难以优化的,对主机总体性能要求也是最高的。由于不只访问量很高,数据量也不小。


针对上面的这些特色和分析,咱们能够对OLTP的得出一个大体的方向。


虽然系统整体数据量较大,可是系统活跃数据在数据总量中所占的比例不大,那么咱们能够经过扩大内存容量来尽量多的将活跃数据cache到内存中;


虽然IO访问很是频繁,可是每次访问的数据量较少且很离散,那么咱们对磁盘存储的要求是IOPS表现要很好,吞吐量是次要因素;


并发量很高,CPU每秒所要处理的请求天然也就不少,因此CPU处理能力须要比较强劲;


虽然与客户端的每次交互的数据量并非特别大,可是网络交互很是频繁,因此主机与客户端交互的网络设备对流量能力也要求不能太弱。


二、典型OLAP应用系统


用于数据分析的OLAP系统的主要特色就是数据量很是大,并发访问很少,但每次访问所须要检索的数据量都比较多,并且数据访问相对较为集中,没有太明显的活跃数据概念。


基于OLAP系统的各类特色和相应的分析,针对OLAP系统硬件优化的大体策略以下:


数据量很是大,因此磁盘存储系统的单位容量须要尽可能大一些;


单次访问数据量较大,并且访问数据比较集中,那么对IO系统的性能要求是须要有尽量大的每秒IO吞吐量,因此应该选用每秒吞吐量尽量大的磁盘;


虽然IO性能要求也比较高,可是并发请求较少,因此CPU处理能力较难成为性能瓶颈,因此CPU处理能力没有太苛刻的要求;


虽然每次请求的访问量很大,可是执行过程当中的数据大都不会返回给客户端,最终返回给客户端的数据量都较小,因此和客户端交互的网络设备要求并非过高;


此外,因为OLAP系统因为其每次运算过程较长,能够很好的并行化,因此通常的OLAP系统都是由多台主机构成的一个集群,而集群中主机与主机之间的数据交互量通常来讲都是很是大的,因此在集群中主机之间的网络设备要求很高。


三、除了以上两个典型应用以外,还有一类比较特殊的应用系统,他们的数据量不是特别大,可是访问请求及其频繁,并且大部分是读请求。可能每秒须要提供上万甚至几万次请求,每次请求都很是简单,可能大部分都只有一条或者几条比较小的记录返回,就好比基于数据库的DNS服务就是这样类型的服务。

虽然数据量小,可是访问极其频繁,因此能够经过较大的内存来cache住大部分的数据,这可以保证很是高的命中率,磁盘IO量比较小,因此磁盘也不须要特别高性能的;


并发请求很是频繁,比须要较强的CPU处理能力才能处理;


虽然应用与数据库交互量很是大,可是每次交互数据较少,整体流量虽然也会较大,可是通常来讲普通的千兆网卡已经足够了。


5、MySQL 锁定机制简介


行级锁定(row-level)

表级锁定(table-level)

页级锁定(page-level)


在MySQL数据库中,使用表级锁定的主要是MyISAM,Memory,CSV等一些非事务性存储引擎,而使用行级锁定的主要是Innodb存储引擎和NDBCluster存储引擎,页级锁定主要是BerkeleyDB存储引擎的锁定方式。


6、MySQL Query的优化


Query语句的优化思路和原则主要提如今如下几个方面:


1. 优化更须要优化的Query;

2. 定位优化对象的性能瓶颈;

3. 明确的优化目标;

4. 从Explain入手;

5. 多使用profile

6. 永远用小结果集驱动大的结果集;

7. 尽量在索引中完成排序;

8. 只取出本身须要的Columns;

9. 仅仅使用最有效的过滤条件;

10.尽量避免复杂的Join和子查询;


合理设计并利用索引


1)B-Tree索引


通常来讲,MySQL中的B-Tree索引的物理文件大多都是以BalanceTree的结构来存储的,也就是全部实际须要的数据都存放于Tree的LeafNode,并且到任何一个LeafNode的最短路径的长度都是彻底相同的,因此咱们你们都称之为B-Tree索引固然,可能各类数据库(或MySQL的各类存储引擎)在存放本身的B-Tree索引的时候会对存储结构稍做改造。如Innodb存储引擎的B-Tree索引实际使用的存储结构其实是B+Tree,也就是在B-Tree数据结构的基础上作了很小的改造,在每个LeafNode上面出了存放索引键的相关信息以外,还存储了指向与该LeafNode相邻的后一个LeafNode的指针信息,这主要是为了加快检索多个相邻LeafNode的效率考虑。


2)Hash索引


Hash索引在MySQL中使用的并非不少,目前主要是Memory存储引擎使用,并且在Memory存储引擎中将Hash索引做为默认的索引类型。所谓Hash索引,实际上就是经过必定的Hash算法,将须要索引的键值进行Hash运算,而后将获得的Hash值存入一个Hash表中。而后每次须要检索的时候,都会将检索条件进行相同算法的Hash运算,而后再和Hash表中的Hash值进行比较并得出相应的信息。


Hash索引仅仅只能知足“=”,“IN”和“<=>”查询,不能使用范围查询;


Hash索引没法被利用来避免数据的排序操做;


Hash索引不能利用部分索引键查询;


Hash索引在任什么时候候都不能避免表扫面;


Hash索引遇到大量Hash值相等的状况后性能并不必定就会比B-Tree索引高;


3)Full-text索引


Full-text索引也就是咱们常说的全文索引,目前在MySQL中仅有MyISAM存储引擎支持,并且也并非全部的数据类型都支持全文索引。目前来讲,仅有CHAR,VARCHAR和TEXT这三种数据类型的列能够建Full-text索引。


索引可以极大的提升数据检索效率,也可以改善排序分组操做的性能,可是咱们不能忽略的一个问题就是索引是彻底独立于基础数据以外的一部分数据,更新数据会带来的IO量和调整索引所致的计算量的资源消耗。


是否须要建立索引,几点原则:较频繁的做为查询条件的字段应该建立索引;惟一性太差的字段不适合单首创建索引,即便频繁做为查询条件;更新很是频繁的字段不适合建立索引;


不会出如今WHERE子句中的字段不应建立索引;


Join语句的优化


尽量减小Join语句中的NestedLoop的循环总次数;“永远用小结果集驱动大的结果集”。


优先优化NestedLoop的内层循环;


保证Join语句中被驱动表上Join条件字段已经被索引;


当没法保证被驱动表的Join条件字段被索引且内存资源充足的前提下,不要太吝惜JoinBuffer的设置;


ORDER BY,GROUP BY和DISTINCT优化


1)ORDER BY的实现与优化


优化Query语句中的ORDER BY的时候,尽量利用已有的索引来避免实际的排序计算,能够很大幅度的提高ORDER BY操做的性能。


优化排序:


1.加大max_length_for_sort_data参数的设置;

2.去掉没必要要的返回字段;

3.增大sort_buffer_size参数设置;


2)GROUP BY的实现与优化


因为GROUP BY实际上也一样须要进行排序操做,并且与ORDER BY相比,GROUP BY主要只是多了排序以后的分组操做。固然,若是在分组的时候还使用了其余的一些聚合函数,那么还须要一些聚合函数的计算。因此,在GROUP BY的实现过程当中,与ORDER BY同样也能够利用到索引。


3)DISTINCT的实现与优化


DISTINCT实际上和GROUP BY的操做很是类似,只不过是在GROUP BY以后的每组中只取出一条记录而已。因此,DISTINCT的实现和GROUP BY的实现也基本差很少,没有太大的区别。一样能够经过松散索引扫描或者是紧凑索引扫描来实现,固然,在没法仅仅使用索引即能完成DISTINCT的时候,MySQL只能经过临时表来完成。可是,和GROUP BY有一点差异的是,DISTINCT并不须要进行排序。也就是说,在仅仅只是DISTINCT操做的Query若是没法仅仅利用索引完成操做的时候,MySQL会利用临时表来作一次数据的“缓存”,可是不会对临时表中的数据进行filesort操做。


7、MySQL数据库Schema设计的性能优化


高效的模型设计


适度冗余-让Query尽可能减小Join


大字段垂直分拆-summary表优化


大表水平分拆-基于类型的分拆优化


统计表-准实时优化


合适的数据类型


75d91a6f0f8712294ed731bc1cef8649.webp


时间存储格式总类并非太多,咱们经常使用的主要就是DATETIME,DATE和TIMESTAMP这三种了。从存储空间来看TIMESTAMP最少,四个字节,而其余两种数据类型都是八个字节,多了一倍。而TIMESTAMP的缺点在于他只能存储从1970年以后的时间,而另外两种时间类型能够存放最先从1001年开始的时间。若是有须要存放早于1970年以前的时间的需求,咱们必须放弃TIMESTAMP类型,可是只要咱们不须要使用1970年以前的时间,最好尽可能使用TIMESTAMP来减小存储空间的占用。


字符存储类型


CHAR[(M)]类型属于静态长度类型,存放长度彻底以字符数来计算,因此最终的存储长度是基于字符集的,如latin1则最大存储长度为255字节,可是若是使用gbk则最大存储长度为510字节。CHAR类型的存储特色是无论咱们实际存放多长数据,在数据库中都会存放M个字符,不够的经过空格补上,M默认为1。虽然CHAR会经过空格补齐存放的空间,可是在访问数据的时候,MySQL会忽略最后的全部空格,因此若是咱们的实际数据中若是在最后确实须要空格,则不能使用CHAR类型来存放。


VARCHAR[(M)]属于动态存储长度类型,仅存占用实际存储数据的长度。TINYTEXT,TEXT,MEDIUMTEXT和LONGTEXT这四种类型同属于一种存储方式,都是动态存储长度类型,不一样的仅仅是最大长度的限制。


事务优化


1. 脏读:脏读就是指当一个事务正在访问数据,而且对数据进行了修改,而这种修改尚未提交到数据库中,这时,另一个事务也访问这个数据,而后使用了这个数据。


2. 不可重复读:是指在一个事务内,屡次读同一数据。在这个事务尚未结束时,另一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,因为第二个事务的修改,那么第一个事务两次读到的的数据多是不同的。这样就发生了在一个事务内两次读到的数据是不同的,所以称为是不可重复读。


3. 幻读:是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的所有数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,之后就会发生操做第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉同样。


Innodb在事务隔离级别方面支持的信息以下:


1.READ UNCOMMITTED


常被成为Dirty Reads(脏读),能够说是事务上的最低隔离级别:在普通的非锁定模式下SELECT的执行使咱们看到的数据可能并非查询发起时间点的数据,于是在这个隔离度下是非Consistent Reads(一致性读);


2.READ COMMITTED


这一隔离级别下,不会出现DirtyRead,可是可能出现Non-RepeatableReads(不可重复读)和PhantomReads(幻读)。


3. REPEATABLE READ


REPEATABLE READ隔离级别是InnoDB默认的事务隔离级。在REPEATABLE READ隔离级别下,不会出现DirtyReads,也不会出现Non-Repeatable Read,可是仍然存在PhantomReads的可能性。


4.SERIALIZABLE


SERIALIZABLE隔离级别是标准事务隔离级别中的最高级别。设置为SERIALIZABLE隔离级别以后,在事务中的任什么时候候所看到的数据都是事务启动时刻的状态,不论在这期间有没有其余事务已经修改了某些数据并提交。因此,SERIALIZABLE事务隔离级别下,PhantomReads也不会出现。


8、可扩展性设计之数据切分


数据的垂直切分


数据的垂直切分,也能够称之为纵向切分。将数据库想象成为由不少个一大块一大块的“数据块”(表)组成,咱们垂直的将这些“数据块”切开,而后将他们分散到多台数据库主机上面。这样的切分方法就是一个垂直(纵向)的数据切分。


垂直切分的优势


◆数据库的拆分简单明了,拆分规则明确;


◆应用程序模块清晰明确,整合容易;


◆数据维护方便易行,容易定位;


垂直切分的缺点


◆部分表关联没法在数据库级别完成,须要在程序中完成;


◆对于访问极其频繁且数据量超大的表仍然存在性能平静,不必定能知足要求;


◆事务处理相对更为复杂;


◆切分达到必定程度以后,扩展性会遇到限制;


◆过读切分可能会带来系统过渡复杂而难以维护。


数据的水平切分


数据的垂直切分基本上能够简单的理解为按照表按照模块来切分数据,而水平切分就再也不是按照表或者是功能模块来切分了。通常来讲,简单的水平切分主要是将某个访问极其平凡的表再按照某个字段的某种规则来分散到多个表之中,每一个表中包含一部分数据。


水平切分的优势


◆表关联基本可以在数据库端所有完成;


◆不会存在某些超大型数据量和高负载的表遇到瓶颈的问题;


◆应用程序端总体架构改动相对较少;


◆事务处理相对简单;


◆只要切分规则可以定义好,基本上较难遇到扩展性限制;


水平切分的缺点


◆切分规则相对更为复杂,很难抽象出一个可以知足整个数据库的切分规则;


◆后期数据的维护难度有所增长,人为手工定位数据更困难;


◆应用系统各模块耦合度较高,可能会对后面数据的迁移拆分形成必定的困难。


数据切分与整合中可能存在的问题


1.引入分布式事务的问题


彻底能够将一个跨多个数据库的分布式事务分拆成多个仅处于单个数据库上面的小事务,并经过应用程序来总控各个小事务。固然,这样做的要求就是咱们的俄应用程序必需要有足够的健壮性,固然也会给应用程序带来一些技术难度。


2.跨节点Join的问题


推荐经过应用程序来进行处理,先在驱动表所在的MySQLServer中取出相应的驱动结果集,而后根据驱动结果集再到被驱动表所在的MySQL Server中取出相应的数据。


3.跨节点合并排序分页问题


从多个数据源并行的取数据,而后应用程序汇总处理。


9、可扩展性设计之Cache与Search的利用


经过引入Cache(Redis、Memcached),减小数据库的访问,增长性能。

经过引入Search(Lucene、Solr、ElasticSearch),利用搜索引擎高效的全文索引和分词算法,以及高效的数据检索实现,来解决数据库和传统的Cache软件彻底没法解决的全文模糊搜索、分类统计查询等功能。


69798b8be115860bdb467b712ee00d2a.jpeg

本文乃《MySQL性能调优与架构设计》读书笔记!


连接:http://www.cnblogs.com/luxiaoxun/p/4694144.html

做者:阿凡卢

出处:http://www.cnblogs.com/luxiaoxun/

相关文章
相关标签/搜索