Mysql的高阶知识之索引的优化

mysql高级知识

mysql的架构介绍

索引优化分析

mysql的简介

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司。
MySQL是一种关联数据库管理系统,将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
Mysql是开源的,所以你不需要支付额外的费用。
Mysql是可以定制的,采用了GPL协议,你可以修改源码来开发自己的Mysql系统。
Mysql支持大型的数据库。可以处理拥有上千万条记录的大型数据库。
MySQL使用标准的SQL数据语言形式。
Mysql可以允许于多个系统上,并且支持多种语言。这些编程语言包括C、C++、Python、Java、Perl、PHP、Eiffel、Ruby和Tcl等。
MySQL支持大型数据库,支持5000万条记录的数据仓库,32位系统表文件最大可支持4GB,64位系统支持最大的表文件为8TB。

mysql的架构介绍

总体概览
和其它数据库相比,MySQL有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在存储引擎的架构上,
插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提取相分离。这种架构可以根据业务的需求和实际需要选择合适的存储引擎。

(这张图重中之重)
在这里插入图片描述
在这里插入图片描述

下面介绍每层的意思
1.连接层
最上层是一些客户端和连接服务,包含本地sock通信和大多数基于客户端/服务端工具实现的类似于tcp/ip的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。

2.服务层
2.1 Management Serveices & Utilities: 系统管理和控制工具
2.2 SQL Interface: SQL接口
接受用户的SQL命令,并且返回用户需要查询的结果。比如select from就是调用SQL Interface
2.3 Parser: 解析器
SQL命令传递到解析器的时候会被解析器验证和解析。
2.4 Optimizer: 查询优化器。
SQL语句在查询之前会使用查询优化器对查询进行优化。
用一个例子就可以理解: select uid,name from user where gender= 1;
优化器来决定先投影还是先过滤。
2.5 Cache和Buffer: 查询缓存。
如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。
这个缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,key缓存,权限缓存等

3.引擎层
存储引擎层,存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过API与存储引擎进行通信。不同的存储引擎具有的功能不同,这样我们可以根据自己的实际需要进行选取。后面介绍MyISAM和InnoDB

4.存储层
数据存储层,主要是将数据存储在运行于裸设备的文件系统之上,并完成与存储引擎的交互。

利用show profile 查看sql的执行周期
先开启 show variables like ‘%profiling%’;
set profiling=1;

select * from xxx ;

show profiles; #显示最近的几次查询
在这里插入图片描述
show profile cpu,block io for query Query_ID #查看程序的执行步骤
在这里插入图片描述
查询流程图:
首先,mysql的查询流程大致是:
mysql客户端通过协议与mysql服务器建连接,发送查询语句,先检查查询缓存,如果命中,直接返回结果,否则进行语句解析,也就是说,在解析查询之前,服务器会先访问查询缓存(query cache)——它存储SELECT语句以及相应的查询结果集。如果某个查询结果已经位于缓存中,服务器就不会再对查询进行解析、优化、以及执行。它仅仅将缓存中的结果返回给用户即可,这将大大提高系统的性能。

语法解析器和预处理:首先mysql通过关键字将SQL语句进行解析,并生成一颗对应的“解析树”。mysql解析器将使用mysql语法规则验证和解析查询;预处理器则根据一些mysql规则进一步检查解析数是否合法。
sql的执行顺序
在这里插入图片描述
#看你的mysql现在已提供什么存储引擎:
show engines;
在这里插入图片描述
#看你的mysql当前默认的存储引擎:
show variables like ‘%storage_engine%’;

在这里插入图片描述
下面介绍mysql里最重要的两个存储引擎MyISAM和InnoDB
1、InnoDB存储引擎
InnoDB是MySQL的默认事务型引擎,它被设计用来处理大量的短期(short-lived)事务。除非有非常特别的原因需要使用其他的存储引擎,否则应该优先考虑InnoDB引擎。

2、MyISAM存储引擎
MyISAM提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等,但MyISAM不支持事务和行级锁,有一个毫无疑问的缺陷就是崩溃后无法安全恢复。

MyISAM和InnoDB区别
MyISAM不支持外键,InnoDB支持外键
MyISAM不支持事务,InnoDB支持事务
MyISAM支持表锁,即使操作一条记录也会锁住整个表,不适合高并发的操作,InnoDB支持行锁,操作时只锁某一行,不对其它行有影响,适合高并发的操作。
MyISAM只缓存索引,不缓存真实数据,InnoDB不仅缓存索引还要缓存真实数据,对内存要求较高,而且内存大小对性能有决定性的影响。

sql写的不好,有可能有一下4个情况
在这里插入图片描述
常见的join图
在这里插入图片描述
索引
索引的目的在于提高查询效率,可以类比字典,
如果要查“mysql”这个单词,我们肯定需要定位到m字母,然后从下往下找到y字母,再找到剩下的sql。
如果没有索引,那么你可能需要a----z,如果我想找到Java开头的单词呢?或者Oracle开头的单词呢?
是不是觉得如果没有索引,这个事情根本无法完成?
一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上

索引优势
类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本
通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗
索引劣势
虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。
实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的

索引的使用场景
在这里插入图片描述
索引的分类

单值索引:即一个索引只包含单个列,一个表可以有多个单列索引
唯一索引:索引列的值必须唯一,但允许有空值
主键索引:设定为主键后数据库会自动建立索引,innodb为聚簇索引
复合索引:即一个索引包含多个列
索引的两个数据结构
BTree索引
在这里插入图片描述
【初始化介绍】
一颗b树,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),
如磁盘块1包含数据项17和35,包含指针P1、P2、P3,
P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。
真实的数据存在于叶子节点即3、5、9、10、13、15、28、29、36、60、75、79、90、99。
非叶子节点只不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。

【查找过程】
如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计,通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时内存中做二分查找找到29,结束查询,总计三次IO。

真实的情况是,3层的b+树可以表示上百万的数据,如果上百万的数据查找只需要三次IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共需要百万次的IO,显然成本非常非常高。
B+Tree索引
在这里插入图片描述
B树和B+树的区别
1)B-树的关键字和记录是放在一起的,叶子节点可以看作外部节点,不包含任何信息;B+树的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。
  2)在B-树中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而B+树中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。从这个角度看B-树的性能好像要比B+树好,而在实际应用中却是B+树的性能要好些。因为B+树的非叶子节点不存放实际的数据,这样每个节点可容纳的元素个数比B-树多,树高比B-树小,这样带来的好处是减少磁盘访问次数。尽管B+树找到一个记录所需的比较次数要比B-树多,但是一次磁盘访问的时间相当于成百上千次内存比较的时间,因此实际中B+树的性能可能还会好些,而且B+树的叶子节点使用指针连接在一起,方便顺序遍历(例如查看一个目录下的所有文件,一个表中的所有记录等),这也是很多数据库和文件系统使用B+树的缘故。
 
思考:为什么说B+树比B-树更适合实际应用中操作系统的文件索引和数据库索引?

  1. B+树的磁盘读写代价更低
      B+树的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。
  2. B+树的查询效率更加稳定
      由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
     聚簇索引与非聚簇索引 
    聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。
    术语‘聚簇’表示数据行和相邻的键值聚簇的存储在一起。
    如下图,左侧的索引就是聚簇索引,因为数据行在磁盘的排列和索引排序保持一致。
    聚簇索引的好处:
    按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不不用从多个数据块中提取数据,所以节省了大量的io操作。
    聚簇索引的限制:
    对于mysql数据库目前只有innodb数据引擎支持聚簇索引,而Myisam并不支持聚簇索引。
    由于数据物理存储排序方式只能有一种,所以每个Mysql的表只能有一个聚簇索引。一般情况下就是该表的主键。
    为了充分利用聚簇索引的聚簇的特性,所以innodb表的主键列尽量选用有序的顺序id,而不建议用无序的id,比如uuid这种。
    索引性能分析:
    Explain(执行计划):
    使用:EXPLAIN + sql语句;
    作用:
    1、表的读取顺序;
    2、数据读取操作的操作类型;
    3、哪些索引可以使用;
    4、那些索引被实际使用;
    5、表之间的引用;
    6、每张表有多少行被优化器查询;
    id
    select 查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序;
    有三种情况:
    1、id相同,执行顺序由上至下;
    2、id不同,如果是子查询,id的序号会递增,id值越大优先级越高,先被执行 ;
    3、id有相同,有不同,相同的可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,先被执行;(table 列中的 derived 的意思是衍生,由 id 衍生的)
    select_type
    在这里插入图片描述
    table
    显示这一行数据是哪个表的;
    type
    性能高低从上到下的顺序;
    possible_keys
    显示可能应用在这张表中的索引,可以是多个;
    查询涉及到的字段上若存在索引,则被列出,但不一定被使用;
    key
    实际使用到的索引,null代表没使用索引。
    查询若使用覆盖索引,则该索引仅出现在key列表中;
    key_len
    表示索引中使用的字节数,越小越好,显示的值为索引字段的最大可能长度,并非实际使用长度。
    ref
    显示索引的哪一列被使用了,最好是常量;
    rows
    根据表统计信息及索引选用情况,大致估计出找到所需的记录所需要读取的行数;
    extra
    包含不适合在其他列展示的但重要的额外信息
    usingwhere 使用where语句;
    usingbuffer 使用缓冲池;
    如果查询的两个表大小相当,那么用in和exists差别不大。
    如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:
    所以无论那个表大,用not exists都比not in要快。not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。
    Join连接索引分析
    单表分析
    例:select id from A where c1 = 1 and c2 > 1 order by v1 desc limit 1;
    建立联合索引(c1,c2,v1),但explain时候发现 type 是range,extra中使用using filesort,这需要优化;
    产生原因:按照BTree索引工作原理,先排序c1,如果c1相同,排序c2,c2相同在排序v1,当c2字段在联合索引中处于中间位置,因为c2 > 1条件是一个范围值(range),MySQL无法利用索引在对后面的v1部分进行索引。所以建立(c1,v1)解决这个问题。

索引失效
1、最好全值匹配;
2、最左前缀法则:如果索引了多列,查询从索引的最左前列开始,且不能跳过索引中的列;
3、不在索引列上做任何操作(计算,函数,类型转换),会导致索引时校而转向全表扫描;
4、存储引擎不能使用索引中范围条件右边的列,即范围之后全失效;
5、尽量使用覆盖索引,只访问索引的查询(索引列和查询列一致),减少selec *;
6、MySQL在使用不等于的时候无法使用索引会导致全表扫描;
7、is null,is not null 也无法使用索引;
8、like 以通配符开头(’%aa‘)索引会失效,变成全表扫描;
9、字符串不加单引号,索引失效;
10、少用 or,用它来连接时候会索引失效
Order By 排序
MySQL支持两种排序,index和fileSort,index效率高,它指MySQL扫描索引本身完成排序。
Order By满足两种情况使用index:
1、Order By 语句使用索引最左前列
2、使用where子句与Order By子句条件组合满足索引最左前列
如果不在索引列上,fileSort有两种算法,4.1版本之前双路排序,进行两次IO;之后单路排序,进行一次IO;
Order By时不要select *,只查询所需要的字段;当两种算法的数据超出sort_buffer的容量会创建tmp文件进行合并运算,导致多次IO,所以需要尝试提高sort_buffer_size 和
max_length_for_sort_ size。
为排序使用索引,MySQL能为排序与查询使用相同的索引
单表
在这里插入图片描述
关联查询优化
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值