首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

MySQL索引的原理,B+树、聚集索引和二级索引的结构分析

在mysql中,存储引擎用类似的方法使用索引,先在索引中找到对应值,然后根据匹配的索引记录找到对应的行。 B树索引 大多数存储引擎都支持B树索引。...B树的查询流程: 如上图我要从找到E字母,查找流程如下: 获取根节点的关键字进行比较,当前根节点关键字为M,E找到指向左边的子节点(二分法规则,左小右大,左边放小于当前节点值的子节点...二级索引和聚集索引的区别是什么呢?二级索引的节点页和聚集索引一样,只存被索引列的值,而二级索引的叶子页除了索引列值,还存这一列对应的主键值。...可以看到,叶子节点存储了整个表的数据,而不是只有索引列,每个叶子节点包含了主键值、事务ID、用于事务和MVCC的回滚指针以及所有的剩余列(col2)。 二级索引分布如下: ?...更新聚集索引列的代较很高,会强制InnoDB将每个被更新的行移动到新的位置。 用二级索引访问数据需要两个索引查找,不是一次。

3.1K30

一文说清楚Mysql Innodb的B+树索引原理及其推理过程

每一页一次,759应该是76次,第76次IO,我们终于找到a为751-760这页数据,然后找到了759这条数据。 是不是太累了?还有没有什么办法优化一下呢?...用数据结构表示如下 [在这里插入图片描述] 上层中存储了书签的页码值和当前书签所对应的书中的位置(指针) 当我们要找759这条数据的时候,我们直接找到上层结构中的701即可找到下层中701所在页的磁盘地址...而如果存储引擎不是Innodb而是MyISAM的话,他的叶子节点存储的不是表数据,而是所在行的指针。 [在这里插入图片描述] 所以MyISAM的主键索引数是非聚簇索引。 什么是二级索引?...在Innodb中,联合索引与主键索引不同的是,叶子节点存储的不是表中的所有数据,而是索引列的数据和主键的值。为什么要存储主键值呢?...对于上诉例子,我们是select *而非select b,c,d,但我们的索引中只是存储了联合索引列的值,也就是b,c,d的值,我们如和找到这一行所有列的值呢?

1.4K20
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    性能大PK count(*)、count(1)和count(列)

    最近的工作中,我听到组内两名研发同学在交流数据统计性能的时候,说到以下内容: 你怎么能用 count(*) 统计数据呢,count(*) 太慢了,要是把数据库搞垮了那不就完了么,用 count(1),这样比较快...InnoDB 是索引组织表,主键索引树的叶子节点是数据,而普通索引树的叶子节点是主键值。因此,普通索引树比主键索引树小很多。对于count(*)这样的操作,遍历哪个索引树得到的结果逻辑上都是一样的。...因此,MySQL优化器会找到最小的那棵树来遍历。 如果你使用过 show table status 命令的话,就会发现这个命令的输出结果里面也有一个 rows 值用于显示这个表当前有多少行。...执行效果上: count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为null count(1)包括了忽略所有列,用1代表代码行,在统计结果的时候,不会忽略列值为null count...(列名)只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是只空字符串或者0,而是表示null 的计数,即某个字段值为null 时,不统计。

    1.6K10

    别再说不懂索引了

    当你想查阅书中某个知识的内容,你会选择一页一页的找呢?还是在书的目录去找呢? 傻瓜都知道时间是宝贵的,当然是选择在书的目录去找,找到后再翻到对应的页。...在创建表时,InnoDB 存储引擎会根据不同的场景选择不同的列作为索引: 如果有主键,默认会使用主键作为聚簇索引的索引键(key); 如果没有主键,就选择第一个不包含 NULL 值的唯一列作为聚簇索引的索引键...的叶子节点里; 二级索引的 B+Tree 的叶子节点存放的是主键值,而不是实际数据。...,而不是实际数据。...主键索引 主键索引就是建立在主键字段上的索引,通常在创建表的时候一起创建,一张表最多只有一个主键索引,索引列的值不允许有空值。

    58020

    常见面试题(笔试题)系列

    而Myisam用一个变量保存了整张表的行数,执行上述语句只需要读出该变量即可,速度很快。 外键:Innodb支持外键,而Myisam不支持。对一个包含外键的Innodb表转为Myisam会失败。...聚簇索引不一定是主键,但是主键一定是聚簇索引。 不建立主键的话是否就没有聚簇索引? 一个表可能没有主键,但是一定会有聚簇索引。因为如果没有定义主键,Innodb就会取第一个非空的唯一索引代替。...id去聚簇索引找到name值。...is_ref,是一个bool值,用来标志这个变量是否属于一个引用集合(其实就是如果用到了引用操作符),通过这个字节,php引擎才能把普通变量和引用变量区分开来。...自动附在HTTP头信息中(这是浏览器自带的功能,用户不会察觉到),当浏览器处理完这个表单后,将结果返回给sessionId所对应的用户(试想,如果没有sessionId,当有两个用户同时注册的时候,服务器怎样才能知道到底哪个用户提交的哪个表单呢

    42930

    图文并茂说MySQL索引——入门进阶必备

    而页10最多存放3条数据记录,所以不得不再分配一个新页。   细心的小伙伴看到此图主键值4的记录在5的后面,别急,下面马上讲到。   这里分配的页号为什么是28而不是11呢?...目录项记录只有主键值和页的编号两个列,而普通的用户记录的列是用户自己定义的,可能包含很多列,另外还有InnoDB自己添加的隐藏列。 那innodb怎么查询呢? 以查找主键为8的记录为例。...比如刚刚的index_demo 表中的c2列的值的大小作为记录和页的排序规则,再建这样一个规则的B+树。 看看这个图,是不是和聚集索引很像?但是还是有点不同。...B+树的叶子结点存储的不是完整的用户记录,没有全部列的信息,只有c2列和主键列这两个列的值。 目录项记录不再是主键+页号,而是c2列+页号。 使用记录c2列的大小进行记录和页的排序。...找到符合c2 = 4的第一条用户记录。找到该记录后,由于只存储了c2列和主键c1,所以需要根据该记录的主键信息到聚集索引中查找完整的用户记录(回表)。

    29210

    MySQL面试题集锦,据说国内外知名互联网公司都在用!

    以下是CHAR和VARCHAR的区别: CHAR和VARCHAR类型在存储和检索方面有所不同 CHAR列长度固定为创建表时声明的长度,长度值范围是1到255 当CHAR值被存储时,它们被用空格填充到特定长度...创建表时TIMESTAMP列用Zero更新。只要表中的其他字段发生更改,UPDATE CURRENT_TIMESTAMP修饰符就将时间戳字段更新为当前时间。 17、主键和候选键有什么区别?...表格的每一行都由主键唯一标识,一个表只有一个主键。 主键也是候选键。按照惯例,候选键可以被指定为主键,并且可以用于任何外键引用。 18、如何使用Unix shell登录MySql?...24、如果一个表有一列定义为TIMESTAMP,将发生什么? 每当行被更改时,时间戳字段将获取当前时间戳。 25、列设置为AUTO INCREMENT时,如果在表中达到最大值,会发生什么情况?...26、怎样才能找出最后一次插入时分配了哪个自动增量? LAST_INSERT_ID将返回由Auto_increment分配的最后一个值,并且不需要指定表名称。 27、你怎么看到为表格定义的所有索引?

    1.8K00

    MySQL索引分类及相关概念辨析

    那为啥99%的情况下都是用B+Tree而不用hash呢? 原因是如果使用范围查找,hash就没有用武之地了,在业务中范围查找是很常用的,但HASH索引不支持,所以基本就不怎么用hash这种数据结构。...相较于主键索引,InnoDB存储引擎的辅助索引会建立另外的一棵B+Tree,这棵索引树的叶子节点的索引位(可以理解为key)就是我们选的索引列,叶子节点的数据位(可以理解为value)为主键值,而不是像主键索引那样索引位是主键...具体怎么算的,不是今天的主题以后再说。 覆盖索引/索引覆盖 是一种索引优化方式而不是索引类型,是指查询的列只需要通过索引树就能查到,不需要二次回表。...使用覆盖索引的一个好处是辅助索引不包含整行记录的所有信息,故其大小要远小于聚集索引,因此可以减少大量的IO操作。所以记住,覆盖索引可以视为索引优化的一种方式,而并不是索引类型的一种。...按照《阿里最新Java编程规范泰山版》中《(二) 索引规约》中的说法: 建议前缀的长度为20区分度高达90%,我认为这不是绝对的,因为通过计算得出的数据才会更具说服力。 那在实际工作中具体如何做呢?

    42940

    MySQL面试题集锦,据说国内外知名互联网公司都在用!

    以下是CHAR和VARCHAR的区别: CHAR和VARCHAR类型在存储和检索方面有所不同 CHAR列长度固定为创建表时声明的长度,长度值范围是1到255 当CHAR值被存储时,它们被用空格填充到特定长度...创建表时TIMESTAMP列用Zero更新。只要表中的其他字段发生更改,UPDATE CURRENT_TIMESTAMP修饰符就将时间戳字段更新为当前时间。 17、主键和候选键有什么区别?...表格的每一行都由主键唯一标识,一个表只有一个主键。 主键也是候选键。按照惯例,候选键可以被指定为主键,并且可以用于任何外键引用。 18、如何使用Unix shell登录MySql?...24、如果一个表有一列定义为TIMESTAMP,将发生什么? 每当行被更改时,时间戳字段将获取当前时间戳。 25、列设置为AUTO INCREMENT时,如果在表中达到最大值,会发生什么情况?...26、怎样才能找出最后一次插入时分配了哪个自动增量? LAST_INSERT_ID将返回由Auto_increment分配的最后一个值,并且不需要指定表名称。 27、你怎么看到为表格定义的所有索引?

    2K00

    MySQL索引分类及相关概念辨析

    那为啥99%的情况下都是用B+Tree而不用hash呢? 原因是如果使用范围查找,hash就没有用武之地了,在业务中范围查找是很常用的,但HASH索引不支持,所以基本就不怎么用hash这种数据结构。...相较于主键索引,InnoDB存储引擎的辅助索引会建立另外的一棵B+Tree,这棵索引树的叶子节点的索引位(可以理解为key)就是我们选的索引列,叶子节点的数据位(可以理解为value)为主键值,而不是像主键索引那样索引位是主键...当通过辅助索引来查询数据时,InnoDB存储引擎会遍历辅助索引并通过叶子节点获得指向主键索引的主键,然后再通过主键索引(聚集索引)来找到一个完整的行记录。这个过程被称为回表。...具体怎么算的,不是今天的主题以后再说。 覆盖索引/索引覆盖 是一种索引优化方式而不是索引类型,是指查询的列只需要通过索引树就能查到,不需要二次回表。...按照《阿里最新Java编程规范泰山版》中《(二) 索引规约》中的说法: 建议前缀的长度为20区分度高达90%,我认为这不是绝对的,因为通过计算得出的数据才会更具说服力。

    55011

    谁还没碰过索引失效呢

    它们区别在于,聚簇索引的叶子节点存放的是实际数据,所有完整的用户数据都存放在聚簇索引的叶子节点,而二级索引的叶子节点存放的是主键值,而不是实际数据。...因为索引保存的是索引字段的原始值,而不是经过函数计算后的值,自然就没办法走索引了。...explain select * from t_user where id = '1'; 为什么第一个例子会导致索引失效,而第二例子不会呢?...MySQL 5.5 的话,前面 a 会走索引,在联合索引找到主键值后,开始回表,到主键索引读取数据行,然后再比对 z 字段的值。...select * from t_user where id = 1 or age = 18; 这是因为 OR 的含义就是两个只要满足一个即可,因此只有一个条件列是索引列是没有意义的,只要有条件列不是索引列

    45140

    别再一知半解啦!索引其实就这么回事!

    专业一点来说呢,索引是一个排好序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址。...同时,为什么我可以直接翻开字典根据字母进行调整呢,这其实不就是因为我的脑子里存在一个大概的「索引表」,知道每个字母大概对应于字典的哪一个位置。虽然是模糊的,但却是真实存在的。...主键索引 即主索引,根据主键建立索引,不允许重复,不允许空值; 主键:数据库表中一列或列组合(字段)的值,可唯一标识表中的每一行。...' ADD FULLTEXT INDEX ft_index('col'); 组合索引 用多个列组合构建的索引,这多个列中的值不允许有空值。...当然主键索引和辅助索引一结合,能干啥呢。当直接采用主键进行检索时,可通过主键索引直接获得数据;而当采用非主键进行检索时,先需要通过辅助索引来获得主键,然后再通过这个主键在主键索引中找到对应的数据行。

    65620

    别再一知半解啦!索引其实就这么回事!

    专业一点来说呢,索引是一个排好序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址。...同时,为什么我可以直接翻开字典根据字母进行调整呢,这其实不就是因为我的脑子里存在一个大概的「索引表」,知道每个字母大概对应于字典的哪一个位置。虽然是模糊的,但却是真实存在的。...主键索引 即主索引,根据主键建立索引,不允许重复,不允许空值; 主键:数据库表中一列或列组合(字段)的值,可唯一标识表中的每一行。...' ADD FULLTEXT INDEX ft_index('col'); 组合索引 用多个列组合构建的索引,这多个列中的值不允许有空值。...当然主键索引和辅助索引一结合,能干啥呢。当直接采用主键进行检索时,可通过主键索引直接获得数据;而当采用非主键进行检索时,先需要通过辅助索引来获得主键,然后再通过这个主键在主键索引中找到对应的数据行。

    65820

    不懂索引,简历上都不敢写自己熟悉SQL优化

    索引类型 面试官:索引有什么用? 大家可以把你最近最爱的一本书类比成一个MySQL数据库,你要快速翻到你昨天看到的精彩部分,是不是要先看下书的目录索引,要翻到第几章、第几页。...实际上叶子节点之间用指针链接形成了一串双向链表。这个留到下文解释。 (3)另外大家很容易漏掉一个重要的知识点。如果是二级索引建立的B-Tree,每个叶子节点的值保存的是对应行数据的主键。...那一级索引叶子节点保存什么呢?一级索引也就是主键索引,下文我会告诉大家。 1.2 B-Tree值的存储 面试官:你说值都存储在叶子节点,那有什么好处?...而B-Tree的二级索引指的是非主键索引,它的叶子节点保存的只是行的主键值,所以需要另外通过主键来找到行数据。 聚簇索引通过主键来建树,它的叶子节点包含了行的全部数据。...=和<>操作,会使索引失效而导致进行全表扫描。 对索引列进行数学函数处理的话,索引会失效。 索引是字符串类型,查询值没有添加单引号''那索引会失效。因为值类型与索引列类型。

    36397

    小胖问我:MySQL 索引的原理是怎样的?(建议收藏)

    (主键约束 = 唯一索引 + 非空值) 唯一索引 索引列中的值必须是唯一的,但是允许为空值。 普通索引 MySQL 中的加索引类型,没啥限制。允许空值和重复值,纯粹为了提高查询效率而存在。...单列索引 没啥好说的,就是索引的列数量只有一个,每个表可以有多个单列索引。 组合索引 多列值组成一个索引,专门用于组合搜索,其效率大于索引合并。注意,使用它的时候需要遵守最左匹配原则。...那 B+ 树在具体的引擎中是怎么发挥作用的呢?一起来看看 3.1 InnDB 索引 首先是 InnDB 索引,篇幅原因,我就聊聊主键索引和普通索引。...流程图 3.1.3 组合索引 如果为每一种查询都设计一个索引,索引是不是太多了?如果我现在要根据学生的姓名去查它的年龄。假设这个需求出现的概览很低,但我们也不能让它走全表扫描吧?...但是为一个不频繁的需求创建一个(姓名)索引是不是有点浪费了?那该咋做呢?我们可以建个(name,age)的联合索引来解决呀。组合索引的结构如下图所示: ?

    69220

    快速查询的秘籍—B+树索引下

    这个特性与聚簇索引一致,只不过把主键换为c2列。 目录项纪录中存放的是c2列+叶号。 B+树的叶子节点存放的数据不是用户记录的全部信息,而是c2列与主键。 那么是怎么查询呢?...在B+树中叶子节点查询出符合要求的c2与主键的值。 每查询出一条就根据主键去聚簇索引中查询我们所需要的记录。...B+树的叶子节点存放的数据不是用户记录的全部信息,而是c2列+c3列+主键。 有一点需要注意,联合索引在创建时,优先根据c2列排序,当c2的值相同时,在根据c3排序。...索引是索引,数据是数据 MyISAM也是用树来存储索引。 1、MyISAM将表数据根据插入顺序全部存放到一个数据文件中。...2、把表的索引信息单独存到索引文件中,每个主键都会创建一个索引信息,然而树的叶子节点存储的是索引+行号信息。在查询时根据索引找到行号,在根据行号找到数据。

    33110

    一文读懂 MySQL 索引 B+树原理!

    如果没有索引,那么你可能需要把所有单词看一遍才能找到你想要的,如果我想找到m开头的单词呢?或者ze开头的单词呢?是不是觉得如果没有索引,这个事情根本无法完成?...比如当(张三,F)这样的数据来检索时,b+树可以用name来指定搜索方向,但下一个字段age的缺失,所以只能把名字等于张三的数据都找到,然后再匹配性别是F的数据了 这个是非常重要的性质,即索引的最左匹配特性...第二个与MyISAM索引的不同是InnoDB的辅助索引data域存储相应记录主键的值而不是地址。换句话说,InnoDB的所有辅助索引都引用主键作为data域。...再例如,用非单调的字段作为主键在InnoDB中不是个好主意,因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,...如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,如下: 此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉

    1.3K10

    主键、聚集索引、辅助索引

    InnoDB 存储引擎将选择建表时第一个定义的非空唯一索引为主键。需要注意的是!主键的选择根据的是非空唯一索引定义的顺序,而不是建表时列的顺序。...比如上面那段代码,有 a、b、c、d 四个列,b、c、d 三列上都有唯一索引。不过 b 列不是非空的,所以不可能成为主键了。...关于 B+ 树的数据结构我就不详细说了,B 代表平衡(Balance),而不是二叉(Binary),B+ 树是从最早的平衡二叉树演化而来的,但是 B+ 树不是一个二叉树。...主键是一种约束,这个约束用来强制表的实体完整性,一个表中只能有一个主键约束,并且主键约束中的列值必须是非空且唯一的。...简单来说,一行记录我们可以用 “主键 + 其他数据” 这样的组合来标识,聚集索引中的叶子节点存储的就是这一整个组合,而非聚集索引中的叶子节点只存储了这个组合中其他数据中的辅助索引键,那剩下的数据我怎么获得呢

    81210

    用流水号当主键不正好么?”

    ,流水号都是单独设置了一个字段,比如叫 trans_no,但是这次就遇到了疑问:trans_no 既然是唯一的,那为什么不直接用 trans_no 当做 id 呢?...MySQL 自增主键而不是使用业务生成的值当做主键。...未声明时,会在 UNIQUE 所有键列所在位置找到第一个索引,NOT NULL 并将其作为聚簇索引 未声明且找不到合适的 UNIQUE 索引,则内部生成一个隐藏的聚簇索引 GEN_CLUST_INDEX..." 补充: 回表:先在二级索引查询到对应的主键值,然后根据主键再去聚簇索引里面取查询。 索引覆盖:二级索引记录了主键列和二级索引列,如果我只查询主键列的值和二级索引列的值,那就不需要回表了。...A: 回表:先在二级索引查询到对应的主键值,然后根据主键再去聚簇索引里面取查询。 索引覆盖:二级索引记录了主键列和二级索引列,如果我只查询主键列的值和二级索引列的值,那就不需要回表了。

    1.9K20

    你知道 Sql 中 left join 的底层原理吗?

    一个是驱动表,那另一个就只能是非驱动表了,在 join 的过程中,其实就是从驱动表里面依次(注意理解这里面的依次)取出每一个值,然后去非驱动表里面进行匹配,那具体是怎么匹配的呢?...上面的 left join 会从驱动表 table A 中依次取出每一个值,然后去非驱动表 table B 中从上往下依次匹配,然后把匹配到的值进行返回,最后把所有返回值进行合并,这样我们就查找到了table...是不是相比匹配7次节省了很多时间。 数据库中的索引一般用 B+ 树,为了让大家更好的理解,我上面画的图只是最简单的一种树结构,而非真实的 B+ 树,但是原理是一样的。...感兴趣的同学可以去看我写的数据结构的文章: 如果索引是主键的话,效率会更高,因为主键必须是唯一的,所以如果被驱动表是用主键去连接,只会出现多对一或者一对一的情况,而不会出现多对多和一对多的情况。...04.Block Nested-Loop Join 理想情况下,用索引匹配是最高效的一种方式,但是在现实工作中,并不是所有的列都是索引列,这个时候就需要用到 Block Nested-Loop Join

    2.1K10
    领券