数据库索引

索引的本质

索引是帮助MySQL高效获取数据的排好序数据结构

  • 索引的数据结构
  1. 二叉排序树
  2. 红黑树(二叉平衡树)
  3. Hash表:对范围查找的支持很差
  4. B-Tree
  • 例子


    image.png

    图1展示一种可能的索引方式。左边是数据表,一共两列七条记录,最左边的是数据记录的物理地址(逻辑上相邻的记录在磁盘上不一定是物理相邻的)。为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点包含索引键值和一个指向对应数据记录物理地址的指针,这样可以运用二叉查找在O(log2)的时间复杂度获取相应数据。

B-Tree

定义一条数据记录为一个二元组[key,data],其中key为记录的键值,对于不同数据记录,key是互不相同的;data为数据记录除key外的数据。

  • 性质
    d为大于1的一个正整数,称为B-Tree的度
    h为一个正整数,称为B-Tree的高度
    每个非叶子节点由n-1个key和n个指针组成,其中d≤n≤2d
    每个叶子节点最少包含一个key和两个指针,最多包含2d-1个key和2d个指针,页节点的指针均为null。
    所有叶节点具有相同的深度,等于树高h。
    key和指针互相间隔,节点两段是指针
  • 叶节点具有哦相同的深度,叶节点的指针为空
  • 所有索引元素不重复
  • 节点中的数据索引从左到右递增排序


    image.png

B+Tree

B-Tree有许多变种,其中最常见的是B+Tree,例如MySQL就普遍使用B+Tree实现其索引结构


image.png

带有顺序访问指针的B+Tree

一般在数据库系统或文件系统中使用的B+Tree结构都在经典B+Tree的基础上进行优化,增加了顺序访问指针


image.png

如图所示,在B+Tree的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的B+Tree。做这个优化的目的是为了提高区间访问的性能,例如图4中如果要查询key为从18到49的所有数据记录,当找到18后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点,从而极大提高区间查询效率。

从计算机组成原理分析B-/+Tree作为索引的理论依据

索引不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上。索引查找过程会产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的复杂度。也就是说索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。
B-Tree每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐就实现一个node只需一次I/O。B-Tree中一次检索最多需要h-1次I/O(根节点常驻内存),复杂度为O(h)=O(logdN)。一般实际应用中,出度d非常大,故h非常小。所以用B-Tree作为索引结构效率非常高。
而红黑树这种结构,h明显要深很多。由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性,所有红黑树的I/O复杂度也为O(h),效率明显比B-Tree差很多。

MySQL索引实现

存储引擎用来形容表的,

MyISAM索引实现

MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。如图设表共有三列,假设以Col1为主键,下图为一个MyISAM表的主索引。可以看出MyISAM的索引文件仅仅保存数据记录的地址。


image.png

在MyISAM中,主索引和辅助索引在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。若以Col2上建立一个辅助索引,则此索引的结构如下图所示:


image.png

同样是一颗B+Tree,data域保存数据记录的地址。因此,MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。
MyISAM的索引方式也叫做“非聚集”的,即索引和数据不在一个文件中。

InnoDB索引实现

InnoDB也使用B+Tree作为索引结构。具体实现方式和MyISAM完全不同。第一个重大区别是InnoDB的数据文件本身就是索引文件。而MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在InnoDB中,表数据文件本身就是按照B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。

  • InnoDB存储表只有两个文件.frm和.ibd(index+data)


    image.png

    可以看出叶节点包含完整的数据记录,这种索引叫做聚集索引。因为
    InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MysqL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整型。
    第二个与MyISAM索引不同的是InnoDB的辅助索引data域存储相应记录主键的值而不是地址,换句话说,InnoDB的所有辅助索引都引用主键作为data域。例如,在col3上定义一个辅助索引:


    image.png

    以英文字符的ASCII码作为比较准则。聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:第一遍检索辅助索引获得主键,然后用主键到主索引中检索获得记录。

常见问题

  • 问题1
    聚集索引:索引和数据聚集在一个文件中,索引和数据放在ibd中,查找只需要一次。
    非聚集索引:索引和数据不聚集一个文件中,即索引放在MYI ,数据放在MYD中,查找需要两次。
    MyISAM存储表有三个文件.frm、.MYD、.MYI
  • 问题2:为什么InnoDB表必须有主键,并且推荐使用整型的自增主键?
    InnoDB必须有主键,即使不手动设置主键,mysql数据库也会默认加一列主键。
    uuid和int区别:
  1. 比较速度上:uuid是一串字符串,比较起来没有整数比较那么简单
  2. 在内存的占用上:uuid会占用更多的内存
    自增
    减少分裂的可能性
  • 问题3:联合索引的底层存储结构?
    分库分表用雪花算法(自增主键),redis也可以。

索引使用策略及优化

MySQL的优化主要分为结构优化和查询优化。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,601评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,367评论 1 305
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,249评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,539评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,967评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,929评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,098评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,825评论 0 207
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,609评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,796评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,282评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,603评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,277评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,159评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,959评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,079评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,874评论 2 277