[TOC]


概述

  • 本质:数据库维护某种数据结构以某种方式引用(指向)数据
  • 索引取舍原则:索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数

B树

满足的条件
  • d为大于1的一个正整数,称为B-Tree的度
  • h为一个正整数,称为B-Tree的高度
  • 每个非叶子节点由n-1个key和n个指针组成,其中d<=n<=2d
  • 每个叶子节点最少包含一个key和两个指针,最多包含2d-1个key和2d个指针,叶节点的指针均为null
  • 所有叶节点具有相同的深度,等于树高h
  • key和指针互相间隔,节点两端是指针
  • 一个节点中的key从左到右非递减排列
  • 所有节点组成树结构
  • 每个指针要么为null,要么指向另外一个节点
  • 一个度为d的B-Tree,设其索引N个key,则其树高h的上限为logd((N+1)/2),检索一个key查找节点的个数的渐进复杂度为logd(N)
更新后的操作
  • 插入删除新的数据记录会破坏B-Tree的性质,因此在插入删除时,需要对树进行一个分裂、合并、转移等操作以保持B-Tree性质

B+树

  • 每个节点的指针上限为2d而不是2d+1
  • 内节点不存储data,只存储key
  • 叶子节点不存储指针
  • 在经典B+树的基础上,增加了顺序访问指针-->提高区间访问的性能

为什么使用B/B+树?

主存读取
  • 当系统需要读取主存时,则将地址信号放到地址总线上传给主存
  • 主存读到地址信号后,解析信号并定位到指定存储单元,然后将此存储单元数据放到数据总线上,供其它部件读取
  • 主存存取的时间仅与存取次数呈线性关系,因为不存在机械操作,两次存取的数据的“距离”不会对时间有任何影响
磁盘存取原理
  • 磁盘转动,每个磁头不动,负责读取内容
  • 不过已经有了多磁头独立技术
  • 局部性原理
  • 磁盘预读:长度一般以页的整数倍为单位

MyISAM索引实现

  • 使用B+树作为索引结构,data存放数据记录的地址
  • 索引文件与数据文件分离
  • 主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复
  • 非聚集:MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录

.MYI文件的组成
  • 整个索引文件的基本信息state
  • 各索引的限制信息base
  • 各索引的定义信息keydef
  • 各索引记录的概要信息recinfo
读取索引的流程
  • query请求,直接读取key cache中的cache block,有就返回
  • 没有就到.MYI文件中以file block方式读取数据
  • 再以相同的格式存取key cache
  • 再将key cache中的数据返回

InnoDB索引实现

  • 也是使用B+树
第一个与MyISAM的不同点
  • 第一个重大区别是InnoDB的数据文件本身就是索引文件,表数据文件本身就是按B+Tree组织的一个索引结构
  • InnoDB的数据文件本身要按主键聚集
  • 所以InnoDB要求表必须有主键(MyISAM可以没有)
  • 没有显式指定,自动选择唯一标识列
  • 不存在的话,生成6个字节长整型的隐含字段
第二个与MyISAM的不同点
  • InnoDB的辅助索引data域存储相应记录主键的值而不是地址
  • 换句话说,InnoDB的所有辅助索引都引用主键作为data域
  • 辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录
得出的优化点
  • 不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大
  • 用非单调的字段作为主键在InnoDB中也不好,因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键就很不错了
  • 聚簇索引键被更新造成的成本除了索引数据可能会移动,相关的所有记录数据也要移动

索引使用策略及优化

全列匹配
  • 按照索引中所有列进行精确匹配(这里精确匹配指“=”或“IN”匹配)时,索引可以被用到
  • 理论上索引对顺序是敏感的,但是由于MySQL的查询优化器会自动调整where子句的条件顺序以使用适合的索引
最左前缀匹配
  • 当查询条件精确匹配索引的左边连续一个或几个列时,索引可以被用到
查询条件用到了索引中列的精确匹配,但是中间某个条件未提供
  • 只能用到索引中,从中间断开前的列
  • 应对
  • 可以增加辅助索引
  • 当中间条件选项较少时,用隔离列的方式,使用IN包含
  • 看情况,比较建立
查询条件没有指定索引第一列
  • 不满足使用索引的条件
匹配某列的前缀字符串
  • 可以使用索引
  • 如果通配符%不出现在开头,则可以用到索引,但根据具体情况不同可能只会用其中一个前缀
范围查询
  • 范围列可以用到索引(必须是最左前缀),但是范围列后面的列无法用到索引
  • 同时,索引最多用于一个范围列,因此如果查询条件中有两个范围列则无法全用到索引
  • 仅用explain可能无法区分范围索引和多值匹配
查询条件中含有函数/表达式
  • 一般不使用哦
  • 手工算好再代入

索引选择性与前缀索引

MyISAM与InnoDB基数统计方式
  • MyisAM索引的基数值(Cardinality,show index 命令可以看见)是精确的,InnoDB则是估计值
  • MyisAM统计信息是保存磁盘中,在alter表或Analyze table操作更新此信息
  • 而InnoDB则是在表第一次打开的时候估计值保存在缓存区内
不建议建立索引的情况
  • 表记录比较少
  • 索引的选择性低:不重复的索引值(也叫基数,Cardinality)与表记录数(#T)的比值
前缀索引
  • 用列的前缀代替整个列作为索引key,当前缀长度合适时,可以做到既使得前缀索引的选择性接近全列索引,同时因为索引key变短而减少了索引文件的大小和维护开销
缺点
  • 不能用于ORDER BY和GROUP BY操作
  • 也不能用于Covering index(即当索引本身包含查询所需全部数据时,不再访问数据文件本身)

InnoDB主键选择与插入优化

  • 如果没有特别的需要,请永远使用一个与业务无关的自增字段作为主键
  • InnoDB使用聚集索引,数据记录本身被存于主索引(一颗B+Tree)的叶子节点上
  • 这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)
  • 如果使用非自增主键,每次插入近似随机,容易引起数据的移动,重新读目标页面,碎片也多了,虽然也可以用OPTIMIZE TABLE重建优化,但麻烦啊

参考资料

  • 图片来源网络
  • 《高性能MySQL》

对B+树与索引在MySQL中的认识的更多相关文章

  1. MySQL索引,MySQL中索引的限制?

    MySQL中索引的限制: 1.MyISAM存储引擎引键的长度综合不能超过1000字节: 2.BLOB和TEXT类型的列只能创建前缀索引: 3.MySQL目前不支持函数索引: 4.使用!= 或者< ...

  2. 索引以及Mysql中的索引

    一.什么是索引 索引是表的目录,会保存在额外的文件中,针对表中的指定列建立,专门用于帮助用户快速查询数据的一种数据结构.类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取 ...

  3. MySQL(五) MySQL中的索引详讲

    序言 之前写到MySQL对表的增删改查(查询最为重要)后,就感觉MySQL就差不多学完了,没有想继续学下去的心态了,原因可能是由于别人的影响,觉得对于MySQL来说,知道了一些复杂的查询,就够了,但是 ...

  4. MySQL中的索引详讲

    一.什么是索引?为什么要建立索引? 索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的 ...

  5. (转)MySQL中的索引详讲

    序言 之前写到MySQL对表的增删改查(查询最为重要)后,就感觉MySQL就差不多学完了,没有想继续学下去的心态了,原因可能是由于别人的影响,觉得对于MySQL来说,知道了一些复杂的查询,就够了,但是 ...

  6. 图解MySQL索引(上)—MySQL有中“8种”索引?

    关于MySQL索引相关的内容,一直是一个让人头疼的问题,尤其是对于初学者来说.笔者曾在很长一段时间内深陷其中,无法分清"覆盖索引,辅助索引,唯一索引,Hash索引,B-Tree索引--&qu ...

  7. Mysql中索引的 创建,查看,删除,修改

    创建索引 MySQL创建索引的语法如下: ? 1 2 3 CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [USING index_type] ON ...

  8. MySQL中的索引优化

    MySQL中的SQL的常见优化策略 MySQL中的索引优化 MySQL中的索引简介 过多的使用索引将会造成滥用.因此索引也会有它的缺点.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行 ...

  9. MySQL中的索引简介

    MySQL中的SQL的常见优化策略 MySQL中的索引优化 MySQL中的索引简介 一. 索引的优点 为什么要创建索引?这是因为,创建索引可以大大提高系统的查询性能. 第一.通过创建唯一性索引,可以保 ...

随机推荐

  1. 1.Struts2简介和Struts2开发环境搭建

    一.Struts2简介: 1.什么是Struts2? 著名的SSH三大框架分别为:表现层(Struts).业务逻辑层(Spring),持久化层(Hibernate). Struts2是在WebWork ...

  2. Delphi TListView刷新闪烁问题

    应用场景 TListView可以动态选择列并显示而且列宽度也要保存,加载数据ListView会出现N次闪烁 步骤一: 选择要显示列: 点击"确定"按钮,显示下图 步骤二: 界面会出 ...

  3. 机器学习 1 linear regression 作业(二)

    这个线性回归的作业需要上传到https://inclass.kaggle.com/c/ml2016-pm2-5-prediction 上面,这是一个kaggle比赛的网站.第一次接触听说这个东西,恰好 ...

  4. Net设计模式实例之适配器模式(Adapter Pattern)

    一.适配器模式简介(Brief Introduction) 适配器模式,将一个类装换成客户期望的另外一个接口.Adapter模式使的原本由于接口不兼容而不能工作的那些类可以一起工作. 二.解决的问题( ...

  5. Xamarin.Android再体验之简单的登录Demo

    一.前言 在空闲之余,学学新东西 二.服务端的代码编写与部署 这里采取的方式是MVC+EF返回Json数据,(本来是想用Nancy来实现的,想想电脑太卡就不开多个虚拟机了,用用IIS部署也好) 主要是 ...

  6. Windows下80端口被pid为4的System进程占用解决方法

    前言 之前是Windows 7系统,前段时间装了Windows 10,php环境还没来得及搭建.今天折腾了一下,是用nginx+php,端口是80(已经停止了iis服务),nginx就是起不来,十之八 ...

  7. css毛玻璃效果

    毛玻璃其实就是磨砂玻璃,能够模糊的看清背后的风景,让人感觉有种朦胧美,让界面看上去有些层次感. 比如: 高大上啊,接下来肯定是眼馋手痒的过程... 当然,用ps搞一个全景毛玻璃背景毫无疑问是最省事的, ...

  8. ASP.NET Core开发-获取所有注入(DI)服务

    获取ASP.NET Core中所有注入(DI)服务,在ASP.NET Core中加入了Dependency Injection依赖注入. 我们在Controller,或者在ASP.NET Core程序 ...

  9. 原生js文字标签云上下滚动播放

    效果:http://hovertree.com/texiao/js/25/ 效果图: 代码如下: <!DOCTYPE html> <html> <head>< ...

  10. 基于CkEditor实现.net在线开发之路(1)

    我以前的公司使用office sharepoint designer为界面设计器,嵌套各种自定义控件,进行各种管理软件,工作流的开发,遇到比较复杂的逻辑,则采用本地写类库,生成DLL上传到服务器,通过 ...