MySQL学习——优化

在系统性能问题中,数据库每每是性能的瓶颈关键因素。那么如何去检测mysql的性能问题,如何构建高性能的mysql,如何编写出高性能的sql语句?为此,整理一些建议。mysql

库表结构优化

  • 尽可能使用简单的字段。
    (1)能用tiny就不要用int
    (2)varchar(n),这里的n只须要知足业务需求便可,没必要取指过大,由于在临时表和排序时,系统可能按照最大长度进行分配内存。

sql查询优化

  • not exists、not in、is not null 在mysql5.7中,这种类型的语句没法使用索引
  • 切分查询:
    一、概念:把大查询切分小查询,每一个查询功能彻底同样,只完成一小部分,每次只返回-- 小部分查询结果。
    二、实例:删除旧数据,按期删除大量数据时,若是用一个大的语句一次性完成的话,则可能须要一次锁住不少数据,占满整个事务日志,耗尽系统资源,阻塞不少小可是重要的查询。例若有sql语句:DELETE FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH);,那么能够采起如下方式进行优化:DELETE FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH) limit 10000;,一次只删除10000行数据通常来讲是一个比较高效而且对服务器影响较小的方法,若是在每次删除之后,隔一段时间再进行删除,能够将服务器上面的压力一次性分散到一个很长的时间段中,就能够大大下降对服务器的影响,还能够大大减小删除时锁的持有时间。
  • 分解关联查询:
    一、概念:不少高性能的应用都会对关联查询进行分解。能够对每个表进行一次单表查询,而后将结果在应用中进行关联。
    二、优势:
    (1)让缓存的效率更高。许多应用程序能够方便的缓存单表查询的结果。另外对于MySQL查询缓存来讲,若是关联的某个表发生了变化,就没法使用查询缓存了,而拆分后,若是某个表不多变化,就能够重复利用查询缓存。
  • 大于>、大于等于>=、小于<、小于等于<=使用索引视状况而定,若是字段是字符串,则不使用索引,若是是

索引优化

  • B-Tree
    一、结构描述:
    图片描述
    (1)全部的值都是按顺序存储的,每个叶子节点到根的距离相同。B-Tree可以加快访问速度,由于按条件查询数据时,若是知足索引查询条件,存储引擎不须要进行全表扫描,而是从索引的根节点开始进行搜索。根节点中存放了指向子节点的指针,存储引擎根据这些指针向下层查找。经过”要查找的值“和“节点页的值”相比较,能够找到适合的指针进入下层节点。最终存储引擎要么找到对应的值的叶子节点,要么找不到。
    (2)叶子节点比较特殊,他们的指针指向被索引的数据。
    (3)树的深度和表的大小直接相关。
    (4)B-Tree对索引列是顺序组织存储的,全部很适合查找范围数据。
    (5)索引树中的节点,因此除了按值查找之外,索引还能够用于查询中的order by操做(按顺序查找)。
    (6)索引存储了实际的列值。
    二、实例:
    假设有table:
    图片描述

    对应的组合索引的结构:
    图片描述
    解读:这里使用last_name、first_name、dob三列做为组合索引。B-Tree索引进行排序的依据是根据建立索引是列的顺序。这里先根据last_name进行排序,相同的话,再依次根据first_name、dob进行排序。
    三、最左原则:
    (1)若是不是按照最左列开始查找,则没法使用索引。好比(a,b,c)这个组合索引,实际上生成(a),(a,b),(a,b,c)三个
    四、优势:
    (1)索引大大减小了数据库服务器须要扫描的数据量
    (2)索引能够帮助数据库服务器避免排序和临时表
    (3)索引能够将随机IO变成顺序IO
    五、没法使用索引的状况:
    (1)索引列不能是表达式的一部分,也不能是函数的参数
    (2)
    六、索引的选择性:
    (1)概念:不重复的索引值和数据表的记录总数的比值
    (2)索引的选择性越高则查询效率越高,由于选择性高的索引可让MySQL在查找时过滤掉更多的行。惟一索引的选择性是1,是性能最好的索引。sql

  • 前缀索引:
    一、概念:使用字符串的前缀做为索引值,加入前缀的选择性足够高,就能利用前缀索引(更小的存储空间)达到优秀的性能。
    二、创建:alter table table_name add key(city(7)); //使用city列的前7个字节做为索引。
    三、缺点:MySQL没法使用前缀索引作order by和group by,覆盖扫描
  • 聚族索引:
    一、概念:聚族索引并非一种索引类型,而是一种数据存储方式。数据行实际上存放在叶子节点中。InnoDB经过主键汇集数据,若是没有定义主键,InnoDB会选择一个惟一的非空索引代替。若是没有这样的索引,InnoDB会隐式定义一个主键来做为聚族索引。
    二、实例:
    图片描述
    这里使用id做为汇集索引
    三、不建议直接用长的字符串(好比UUID)做为主键,这样子的话,InnoDB使用主键做为聚族索引,将致使页分裂,影响性能。
    四、回表:因为数据行存储在索引中,因此能通索引直接找到数据行,能够避免再到数据表中进行查找数据(也就是回表)。

分表、分库

检查耗时

show profiles 用于查看执行语句的耗时,不过默认状况下,profiles是关闭的,能够经过set profiling=1;开启profiles。经过select @@profiling; 查看profiles是否开启了。数据库

explain

这里主要对explain查询结果的参数进行说明。缓存

type:该字段代表数据库引擎查找表的方式。常见的有all、index、range、ref、eq_ref、const。从左到右,它们的效率依次是加强的。撇开sql的具体应用环境以及其余因素,你应当尽可能优化你的sql语句,使它的type尽可能靠右,但实际运用中仍是要综合考虑各个方面的。下面具体讲下这几种常见的类型:
(1)all:这即是所谓的“全表扫描”,若是是展现一个数据表中的所有数据项,却是以为也没什么,若是是在一个查找数据项的sql中出现了all类型,那一般意味着你的sql语句处于一种最原生的状态,有很大的优化空间。
(2)index:索引全扫描。type=index状况下,扫描的是索引,可是会扫描全部的索引。因为索引是有序的,而且索引文件一般比数据文件小。,因此效率会优于all
(3)range:range指的是有范围的索引扫描,相对于index的全索引扫描,它有范围限制,所以要优于index。关于range比较容易理解,须要记住的是出现了range,则必定是基于索引的。同时除了显而易见的between,and以及'>','<'外,in和or也是索引范围扫描。
(4)ref:出现该链接类型的条件是: 查找条件列使用了索引并且不为主键和unique。其实,意思就是虽然使用了索引,但该索引列的值并不惟一,有重复。这样即便使用索引快速查找到了第一条数据,仍然不能中止,要进行目标值附近的小范围扫描。但它的好处是它并不须要扫全表,由于索引是有序的,即使有重复值,也是在一个很是小的范围内扫描。实例以下,cname为非惟一索引:
图片描述服务器

(5)ref_eq:对于每一个来自于前面的表的行组合,从该表中读取一行(而且使用了主键或者惟一性索引进行查找的状况)。这多是最好的联接类型,除了const类型。实例以下:
图片描述
(6)const:一般状况下,若是将一个主键放置到where后面做为条件查询,mysql优化器就能把此次查询优化转化为一个常量。(表最多有一个匹配行)
(7)system:表仅有一行(=系统表)。这是const联接类型的一个特例(此次存疑,由于表只有一行的状况下,使用主键查询,显示type=const)mysql优化

possible_keys:可能用到的索引函数

key:实际用到的索引性能

key_len:MySQL决定使用的键长度。若是键是NULL,则长度为NULL。key_len的计算.
(1)全部的索引字段,若是没有设置not null,则须要加一个字节。
(2)定长字段,int占四个字节、date占三个字节、char(n)占n个字符。
(3)对于变成字段varchar(n),则有n个字符+两个字节。
(4)不一样的字符集,一个字符占用的字节数不一样。latin1编码的,一个字符占用一个字节,gbk编码的,一个字符占用两个字节,utf8编码的,一个字符占用三个字节。优化

ref:是经过常量const,或是某个表的某个字段来过滤的。常见的值有 const, func, NULL, 具体字段名。当 key 列为 NULL ,即不使用索引时,此值也相应的为 NULL。编码

rows:估计须要扫描的行数

Extra:显示以上信息以外的其余信息
(1)Distinct:MySQL发现第1个匹配行后,中止为当前的行组合搜索更多的行。
(2)Not exists:MySQL可以对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,再也不为前面的的行组合在该表内检查更多的行。
(3)range checked for each record (index map: #):MySQL没有发现好的可使用的索引,但发现若是来自前面的表的列值已知,可能部分索引可使用。
(4)Using filesort:MySQL须要额外的一次传递,以找出如何按排序顺序检索行。
(5)Using index:从只使用索引树中的信息而不须要进一步搜索读取实际的行来检索表中的列信息。
(6)Using temporary:为了解决查询,MySQL须要建立一个临时表来容纳结果。
(7)Using where:WHERE 子句用于限制哪个行匹配下一个表或发送到客户。
(8)Using sort_union(...), Using union(...), Using intersect(...):这些函数说明如何为index_merge联接类型合并索引扫描。
(9)Using index for group-by:相似于访问表的Using index方式,Using index
(10)for group-by表示MySQL发现了一个索引,能够用来查 询GROUP BY或DISTINCT查询的全部列,而不要额外搜索硬盘访问实际的表。

filtered : 显示了经过条件过滤出的行数的百分比估计值。

参考:
《高性能mysql》
https://blog.csdn.net/dennis2...

相关文章
相关标签/搜索