MySQL优化及索引解析

索引简单介绍

索引的本质:

  • MySQL索引或者说其他关系型数据库的索引的本质就只有一句话,以空间换时间。

索引的作用:

  • 索引关系型数据库为了加速对表中行数据检索的(磁盘存储的)数据结构

索引的分类

数据结构上面的分类:

  • HASH 索引

    • 等值匹配效率高
    • 不支持范围查找
  • 树形索引
    • 二叉树,递归二分查找法,左小右大
    • 平衡二叉树,二叉树到平衡二叉树,主要原因是左旋右旋
    • 缺点1,IO次数过多
    • 缺点2,IO利用率不高,IO饱和度
  • 多路平衡查找树(B-Tree)
    • 特点,大大的减少了树的高度
  • B+树
    • 特点,采用左闭合的比较方式
    • 根节点支节点没有数据区,只有叶子结点才包含数据区(说白了就是即便在根节点和子节点已经定位到,因为没有数据区的原因也不会停留,会一直找到叶子结点为止。)

当我们搜索13这条数据时,在根节点和子节点 都能定位,但是一直会找到叶子结点。

二叉树平衡二叉树,B树对比:

如图显示如果是自增主键情况下:

二叉树显然不适合做关系型数据库索引(和全表扫描没什么区别)。

平衡二叉树呢,虽然解决了这种情况,但是同样会导致这棵树,又瘦又高,这同样会造成上文所提到查询IO次数过多以及IO利用率不高。

B树呢,显然已经解决了这两个问题,所以下文来解释,为什么在这种情况下MySQL还用了B+树,又做了那些增强。

B树和B+树比较:

B+树在B树上面的优化:

IO效率更高(B树每个节点都会保留数据区,而B+树则不会,假设我们查询一条数据要遍历三层,那么显然B+树查询中IO消耗更小)

范围查找效率更高(如图,B+树已经形成了一个天然链表形式,只需要根据最结尾的链式结构查找)

基于索引的数据扫描效率更高。

索引类型的分类

索引类型可分为两类:

  • 主键索引
  • 辅佐索引(二级索引)
    • 唯一性索引
    • 复合索引
    • 普通索引
    • 覆盖索引

主键索引相对来说性能是最好的,但是对于SQL优化,其实大多时候我们都在辅佐索引上面做一些改进和补充。

B+树在储存引擎层面落地

  • 我们创建两个表分别为test_innodb(采用InnoDB作为储存引擎)test_myisam(采用MyISAM作为储存引擎)下图是两张表磁盘落地的相关文件,这两个储存引擎在B+树磁盘落地式截然不同的。

B+树在MyISAM落地:

  • *.frm文件是表格骨架文件比如这个表中的id字段name字段是什么类型的存储在这里
  • *.MYD(D=data)则储存数据
  • *.MYI (I=index)则储存索引

  • 比如现在执行如下sql语句 ,那么在MyISAM中他就是先在test_myisam.MYI中查找到103然后拿到0x194281这个地址然后再去test_myisam.MYD中找到这个数据返回。
SELECT id,name from test_myisam where id =103

  • 如果test_myisam表中,id为主键索引,name也是一个索引,那么在test_myisam.MYI中则会有两个平级的B+树,这也导致MyISAM引擎中主键索引和二级索引是没有主次之分的,是平级关系。因为这种机制在MyISAM引擎中,有可能使用多个索引,在InnoDB中则不会出现这种情况。

B+树在InnoDB落地:

  • InnoDB不像MyISAM来独立一个MYD 文件来存储数据,它的数据直接存储在叶子结点关键字对应的数据区在这保存这一个id列所有行的详细记录。
  • InnoDB 主键索引和辅助索引关系

我们现在执行如下SQL语句,他会先去找辅助索引,然后找到辅助索引下101的主键,再去回表(二次扫描)根据主键索引查询103这条数据将其返回。

SELECT id,name from test_myisam where name ='zhangsan'

这里就有一个问题了,为什么不像MyISAM在辅助索引下直接记录磁盘地址,而是要多此一举再去回表扫描主键索引,这个问题在下面相关面试题中回答,记一下这个问题是这里来的。

相关面试题

  • 为什么MySQL选择B+树作为索引结构

这个就不说了,上文应该讲清楚了。

  • B+树在MyISAM和InnoDB落地区别。

这个可以总结一下,MyISAM落地数据储存会有三个类型文件 ,.frm文件是表骨架文件,.MYD(D=data)则储存数据 ,.MYI (I=index)则储存索引,MyISAM引擎中主键索引和二级索引平级关系,在MyISAM引擎中,有可能使用多个索引,InnoDB则相反,主键索引和二级索有严格的主次之分在InnoDB一条语句只能用一个索引要么不用。

  • 如何判断一条sql语句是否使用了索引。

可以通过执行计划来判断 可以在sql语句前explain/ desc

set global optimizer_trace='enabled=on' 打开执行计划开关他将会把每一条查询sql执行计划记录在information_schema 库中OPTIMIZER_TRACE表中

  • 为什么主键索引最好选择自增列?

自增列,数据插入时整个索引树是只有右边在增加的,相对来说索引树的变动更小。

  • 为什么经常变动的列不建议使用索引?

和上一个问题原因一样,当一个索引经常发生变化,那么就意味这,这个缩印树也要经常发生变化。4

  • 为什么说重复度高的列,不建议建立索引?

这个原因是因为离散性,比如说,一张一百万数据的表,其中一个字段代表性别,0代表男1代表女,把这字段加了索引,那么在索引树上,将会有大量的重复数据。而我们常见的索引建立一般都是驱动型的。其目的是,尽可能的删减数据的查询范围,这个显然是不匹配的。

  • 什么是联合索引

联合索引是一个包含了多个功效的索引,他只是一个索引而不是多个,

其次,单列索引是一种特殊的联合索引

联合索引的创立要遵循最左前置原则(最常用列>离散度>占用空间小)

  • 什么是覆盖索引

通过索引项信息可直接返回所需要查询的索引列,该索引被称之为覆盖索引,说白了就是不需要做回表操作,可以从二级索引中直接取到所需数据。

  • 什么是ICP机制

索引下推,简单点来说就是,在sql执行过程中,面对where多条件过滤时,通过一个索引,完成数据搜索和过滤条件其,特点能减少io操作。

  • 在InnoDB表中不可能没有主键对还是不对原因是什么?

首先这句话是对的,但是情况有三种:

  • 就是在你手动显式指定这一个字段为主键时候,会以这一个字段为聚集索引。
  • 在没有显式指定主键时候有两种情况:
  • 他会寻找第一个UK(unique key)作为主键索引组织索引编排。
  • 如果既没有指定主键也没有UK的情况下,此时会以rowId(在InnoDB表中每一个记录都会有一个隐藏(6byte)的rowId)为聚集索引。
  • 什么是回表操作

在InnoDB 中基于辅助索引查询的内容,从辅助索引中无法直接获取,需要基于主键索引的二次扫描的操作叫做回表操作。

  • 为什么在InnoDB 中辅助索引叶子结点数据区记录的是主键索引的值而不是像MyISAM中去记录磁盘地址。

这个原因其实很简单,因为主键索引的数据结构是会经常发生变化的,如果在辅助索引数据区记录磁盘地址,那么假设我们有10个辅助索引,当我们主键索引结构发生变化后,还要一个个去通知辅助索引,且主键索引结构是经常发生变化的,增删都有可能影响他的
数据结构。

到此这篇关于MySQL优化及索引解析的文章就介绍到这了,更多相关MySQL优化索引内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Mysql性能优化之索引下推

    索引下推(index condition pushdown )简称ICP,在Mysql5.6的版本上推出,用于优化查询. 在不使用ICP的情况下,在使用非主键索引(又叫普通索引或者二级索引)进行查询时,存储引擎通过索引检索到数据,然后返回给MySQL服务器,服务器然后判断数据是否符合条件 . 在使用ICP的情况下,如果存在某些被索引的列的判断条件时,MySQL服务器将这一部分判断条件传递给存储引擎,然后由存储引擎通过判断索引是否符合MySQL服务器传递的条件,只有当索引符合条件时才会将数据检索出

  • 一文教你MySQL如何优化无索引的join

    目录 前言 遍历循环查询 join 查询 join buffer (Block Nested Loop) 附:mysql  join查询没有走索引的原因 总结 前言 MySQL Join 你用过吗?你知道其中的原理吗? 现在有张 user 表,这个 user 表很简单,一个主键 id,也就是我们的用户 id,还有个 name 字段,很明显就是用户的姓名. 这时候还有一张 user_info 表,这个 user_info 表存的是用户的一些其他信息,有 user_id 代表用户的 id,还有个 a

  • mysql千万级数据量根据索引优化查询速度的实现

    (一)索引的作用 索引通俗来讲就相当于书的目录,当我们根据条件查询的时候,没有索引,便需要全表扫描,数据量少还可以,一旦数据量超过百万甚至千万,一条查询sql执行往往需要几十秒甚至更多,5秒以上就已经让人难以忍受了. 能在软件上解决的,就不在硬件上解决,毕竟硬件提升代码昂贵,性价比太低.代价小且行之有效的解决方法就是合理的加索引.索引使用得当,能使查询速度提升上千倍,效果惊人. (二)mysql的索引类型: mysql的索引有5种:主键索引.普通索引.唯一索引.全文索引.聚合索引(多列索引).

  • MySQL的索引原理以及查询优化详解

    目录 一.介绍 1.什么是索引? 2.为什么要有索引呢? 二.索引的原理 一 索引原理 二 磁盘IO与预读 三.索引的数据结构 四.Mysql索引管理 一.功能 二.MySQL的索引分类 三. 索引的两大类型hash与btree 四.创建/删除索引的语法 五.测试索引 1.准备 2 .在没有索引的前提下测试查询速度 3. 加上索引 六.正确使用索引 一.覆盖索引 二.联合索引 三.索引合并 七.慢查询优化的基本步骤 总结 一.介绍 1.什么是索引? 一般的应用系统,读写比例在10:1左右,而且插

  • MySQL数据优化-多层索引

    目录 一.多层索引 1.创建 2.设置索引的名称 3.from_arrays( )-from_tuples() 4.笛卡儿积方式 二.多层索引操作 1.Series 2.DataFrame 3.交换索引 4.索引排序 5.索引堆叠 6.取消堆叠 一.多层索引 1.创建 环境:Jupyter import numpy as np import pandas as pd a=pd.DataFrame(np.random.random(size=(4,4)),index=[['上半年','上半年','

  • Mysql索引选择以及优化详解

    索引模型 哈希表 适用于只有等值查询的场景,Memory引擎默认索引 InnoDB支持自适应哈希索引,不可干预,由引擎自行决定是否创建 有序数组:在等值查询和范围查询场景中的性能都非常优秀,但插入和删除数据需要进行数据移动,成本太高.因此,只适用于静态存储引擎 二叉平衡树:每个节点的左儿子小于父节点,父节点又小于右儿子,时间复杂度是 O(log(N)) 多叉平衡树:索引不止存在内存中,还要写到磁盘上.为了让一个查询尽量少地读磁盘,就必须让查询过程访问尽量少的数据块.因此,要使用"N 叉"

  • MySQL索引优化之分页探索详细介绍

    目录 ​​MySQL​​索引优化之分页探索 案例一 案例二 ​​MySQL​​索引优化之分页探索 表结构 CREATE TABLE `demo` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '姓名', `age` int(11) NOT NULL DEFAULT '0'

  • MySQL优化及索引解析

    索引简单介绍 索引的本质: MySQL索引或者说其他关系型数据库的索引的本质就只有一句话,以空间换时间. 索引的作用: 索引关系型数据库为了加速对表中行数据检索的(磁盘存储的)数据结构 索引的分类 数据结构上面的分类: HASH 索引 等值匹配效率高 不支持范围查找 树形索引 二叉树,递归二分查找法,左小右大 平衡二叉树,二叉树到平衡二叉树,主要原因是左旋右旋 缺点1,IO次数过多 缺点2,IO利用率不高,IO饱和度 多路平衡查找树(B-Tree) 特点,大大的减少了树的高度 B+树 特点,采用

  • mysql性能优化之索引优化

    作为免费又高效的数据库,mysql基本是首选.良好的安全连接,自带查询解析.sql语句优化,使用读写锁(细化到行).事物隔离和多版本并发控制提高并发,完备的事务日志记录,强大的存储引擎提供高效查询(表记录可达百万级),如果是InnoDB,还可在崩溃后进行完整的恢复,优点非常多.即使有这么多优点,仍依赖人去做点优化,看书后写个总结巩固下,有错请指正. 完整的mysql优化需要很深的功底,大公司甚至有专门写mysql内核的,sql优化攻城狮,mysql服务器的优化,各种参数常量设定,查询语句优化,主

  • MySQL优化中B树索引知识点总结

    为什么要进行SQL优化呢?很显然,当我们去写sql语句时: 1会发现性能低 2.执行时间太长, 3.或等待时间太长 4.sql语句欠佳,以及我们索引失效 5.服务器参数设置不合理 SQL语句执行过程分析 1.编写过程: 编写过程就是我们平常写sql语句的过程,也可以理解为编写顺序,以下就是我们编写顺序: select from join on where 条件 group by 分组 having过滤组 order by排序 limit限制查询个数 我们虽然是这样去写的,但是它mysql的引擎去

  • Mysql数据库之索引优化

    MySQL凭借着出色的性能.低廉的成本.丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库.虽然性能出色,但所谓"好马配好鞍",如何能够更好的使用它,已经成为开发工程师的必修课,我们经常会从职位描述上看到诸如"精通MySQL"."SQL语句优化"."了解数据库原理"等要求.我们知道一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,

  • MySQL Order By索引优化方法

    尽管 ORDER BY 不是和索引的顺序准确匹配,索引还是可以被用到,只要不用的索引部分和所有的额外的 ORDER BY 字段在 WHERE 子句中都被包括了. 使用索引的MySQL Order By 下列的几个查询都会使用索引来解决 ORDER BY 或 GROUP BY 部分: 复制代码 代码如下: SELECT * FROM t1 ORDER BY key_part1,key_part2,... ; SELECT * FROM t1 WHERE key_part1=constant ORD

  • MySQL索引背后的之使用策略及优化(高性能索引策略)

    本章的内容完全基于上文的理论基础,实际上一旦理解了索引背后的机制,那么选择高性能的策略就变成了纯粹的推理,并且可以理解这些策略背后的逻辑. 示例数据库 为了讨论索引策略,需要一个数据量不算小的数据库作为示例.本文选用MySQL官方文档中提供的示例数据库之一:employees.这个数据库关系复杂度适中,且数据量较大.下图是这个数据库的E-R关系图(引用自MySQL官方手册): 图12 MySQL官方文档中关于此数据库的页面为http://dev.mysql.com/doc/employee/en

  • MySQL优化GROUP BY(松散索引扫描与紧凑索引扫描)

    满足GROUP BY子句的最一般的方法是扫描整个表并创建一个新的临时表,表中每个组的所有行应为连续的,然后使用该临时表来找到组并应用累积函数(如果有).在某些情况中,MySQL能够做得更好,即通过索引访问而不用创建临时表.        为GROUP BY使用索引的最重要的前提条件是所有GROUP BY列引用同一索引的属性,并且索引按顺序保存其关键字.是否用索引访问来代替临时表的使用还取决于在查询中使用了哪部分索引.为该部分指定的条件,以及选择的累积函数.        由于GROUP BY 实

  • 探究MySQL优化器对索引和JOIN顺序的选择

    本文通过一个案例来看看MySQL优化器如何选择索引和JOIN顺序.表结构和数据准备参考本文最后部分"测试环境".这里主要介绍MySQL优化器的主要执行流程,而不是介绍一个优化器的各个组件(这是另一个话题). 我们知道,MySQL优化器只有两个自由度:顺序选择:单表访问方式:这里将详细剖析下面的SQL,看看MySQL优化器如何做出每一步的选择. explain select * from employee as A,department as B where A.LastName = '

随机推荐