5-01 Mysql索引底层数据结构与算法
2022-12-07 14:26:02 2 举报
01 Mysql索引底层数据结构与算法
作者其他创作
大纲/内容
<b>索引</b>
是帮助Mysql高效获取数据的<b>排好序</b>的<b>数据结构</b>
<b>索引数据结构</b>
以下图数据表查询为例:
<b>二叉树</b>
<b><font color="#2196f3">二叉树</font></b>结构:
二叉树示意图:
与<font color="#4caf50"><b>不使用索引</b></font>时比较:
以<b>查询Col2=89</b>为例,此列数据为<b>非连续非顺序</b>的
在<b><font color="#4caf50">不使用索引</font></b>情况查询,需要<b><font color="#4caf50">查找6次</font></b>后可得到结果,如下图所示:
使用<b><font color="#2196f3">二叉树</font></b>结构查询,仅需要<b><font color="#2196f3">查找2次</font></b>即可得到结果,如下图所示:
<font color="#000000" style="">但</font><font color="#f44336" style="font-weight: bold;">Mysql索引</font>底层数据结构并<b><font color="#f44336">未采用</font><font color="#2196f3">二叉树</font></b>结构
<font color="#000000"><b style="">原因1</b>:</font>
以<b>查询Col1=6</b>为例(此列<b>数据</b>是<b>顺序递增</b>的)
在使用<b style=""><font color="#2196f3">二叉树</font></b>情况下查询,需要<b><font color="#2196f3">查找6次</font></b>后才可得到结果,如下图所示:
<font color="#000000">此时,与</font><font color="#4caf50"><b>未使用索引</b></font><font color="#000000">情况下时</font><b style=""><font color="#f44336">查询次数一样</font></b><font color="#000000">,并</font><b style=""><font color="#f44336">未提高查询效率</font></b>
<font color="#000000"><b style="">原因2</b>:</font>
<font color="#000000">在</font><font color="#000000" style=""><b>百万级数据量</b>或<b>更高</b></font><font color="#000000">的情况下,</font><b style=""><font color="#2196f3">二叉树</font></b><font color="#f44336"><b>层级过多</b></font><font color="#f57c00">,</font><b style=""><font color="#f44336">树的高度不可控</font></b><font color="#f57c00">,</font><font color="#000000">会很高很高,当</font><b style=""><font color="#f44336">查询结果为叶子节点</font></b><font color="#000000">时</font><b style=""><font color="#f44336">查询效率下降</font></b><font color="#000000">明显</font>
<b>红黑树</b>
<b><font color="#2196f3">红黑树</font></b>结构:
红黑树结构示意图1:
红黑树结构示意图2:
与使用<b><font color="#4caf50">二叉树</font></b>时比较:
以<b>查询Col1=6</b>为例,此列数据是<b>顺序递增</b>的
在使用<b style=""><font color="#4caf50">二叉树</font></b>情况下查询,需要<b><font color="#4caf50">查找6次</font></b>后才可得到结果,如下图所示:
在使用<b><font color="#2196f3">红黑树</font></b>情况下查询,只需要<b style="color: rgb(33, 150, 243);">查找3次</b><font color="#000000">就</font>可得到结果,如下图所示:
相对<b><font color="#4caf50">二叉树</font></b>来说,<b><font color="#2196f3">红黑树</font>对于<font color="#2196f3">单边操作</font>时,他会做一次<font color="#2196f3">平衡</font></b>
但<b><font color="#f44336">Mysql索引</font></b>底层数据结构<b><font color="#f44336">也</font></b>并<b style=""><font color="#f44336">未采用</font><font color="#2196f3">红黑</font></b><b><font color="#2196f3">树</font></b>结构
<b><font color="#000000">原因:</font></b>
<font color="#000000">在</font><b style="color: rgb(0, 0, 0);">百万级数据量</b><font color="#000000">或</font><b style="color: rgb(0, 0, 0);">更高</b><font color="#000000">的情况下,与</font><b style=""><font color="#4caf50">二叉树</font></b><b style=""><font color="#f44336">一样</font></b><font color="#000000">,</font><font color="#f44336"><b>层级过多</b></font><font color="#000000">,</font><b style=""><font color="#f44336">树的高度不可控</font></b><font color="#000000">,会很高很高,当</font><b style=""><font color="#f44336">查询结果为叶子节点</font></b><font color="#000000">时</font><b style=""><font color="#f44336">查询效率下降</font></b><font color="#000000">明显</font>
<b>B-Tree</b>
<b><font color="#2196f3">B-Tree</font></b>结构:
B-Tree示<b>大体</b>意图:
B-Tree示<b>细节</b>意图:
<font color="#2196f3"><b>B-Tree</b></font><font color="#000000">特征</font><font color="#2196f3">:</font>
<b>叶子节点</b>具有<b>相同的深度</b>,<b>叶子节点</b>的<b>指针为空</b>
<b>所有索引</b>元素<b>不重复</b>
节点中数据<b>索引从左到右递增</b>排列
与<font color="#4caf50"><b>红黑树</b>、<b>二叉树</b></font>比较:
以查询<b>Col2=89</b>为例(此列<b>数据</b>为<b>非连续非顺序</b>的)
使用<b><font color="#2196f3">B-Tree</font></b>结构查询,也仅需要<b><font color="#2196f3">查找2次</font></b>即可得到结果,如下图所示:
以<b>查询Col1=6</b>为例(此列<b>数据</b>为<b>连续递增</b>的)
使用<b><font color="#2196f3">B-Tree</font></b>结构查询,仅需要<b><font color="#2196f3">查找2次</font></b>即可得到结果,如下图所示:
但<b><font color="#f44336">Mysql索引</font></b>底层数据结构<b><font color="#f44336">也</font></b>并<b><font color="#f44336">未采用</font><font color="#2196f3">B-Tree</font></b>结构
<b><font color="#000000">原因:</font></b>
由<b><font color="#2196f3">B-Tree</font></b>示细节意图,可看出每个<b><font color="#f44336">节点存放data</font></b>会<b><font color="#f44336">占用节点资源</font></b>,<b><font color="#f44336">减少节点</font></b>中的<b><font color="#f44336" style="">索引元素数量</font></b>,在大数据量时会增加树的层级,即<b><font color="#f44336">增加了查找次数</font></b>。
<b><font color="#2196f3">B-Tree</font></b> 进行<b><font color="#f44336">数据范围查询</font></b>时,由于<b><font color="#f44336">节点之间未使用指针连接</font></b>,范围查询<b><font color="#f44336">每次</font></b>都需要<b><font color="#f44336">从根节点开始查找</font></b>。
<b>B+Tree</b>
<b><font color="#2196f3">B+Tree</font></b>结构:
<b><font color="#4caf50">普通的B+Tree</font></b>示意图:
<font color="#2196f3"><b>MySQL改造的B+Tree</b></font>示意图2:
<b><font color="#2196f3">B+Tree</font></b>特征:
<b>非叶子</b>节点<b>不存储data</b>,<b>只存储</b><font color="#e57373"><b>(冗余)</b></font><b>索引</b>,这样可以放更多的索引
<b>叶子节点</b>包含<b>所有索引</b>字段<br>
<b>叶子节点</b>用<b>指针连接</b>,提高区间访问的性能<br>
与<b><font color="#4caf50">普通的B+Tree</font></b>相比,<b><font color="#2196f3">MySQL改造的B+Tree</font></b>的叶子节点之间为<b><font color="#2196f3">双向指针连接</font></b>
与<b><font color="#4caf50">B-Tree</font></b>相比较:
1、<font color="#2196f3" style="font-weight: bold;">B+Tree非叶子节点不存储data</font><b>,</b><b style=""><font color="#2196f3">比</font></b><font color="#4caf50" style="font-weight: bold;">B-Tree</font><font style="font-weight: bold;" color="#2196f3">可以存放更多的索引</font>,<b><font color="#f44336">差异如下</font></b>图:
a. <b><font color="#4caf50">B-Tree</font></b>结构图:
b. <b><font color="#2196f3">B+Tree</font></b>结构图:
2、<b><font color="#2196f3">B+Tree非叶子节点只存储冗余的索引</font></b>,<b><font color="#f44336">差异如下</font></b>图:
a. <b><font color="#4caf50">B-Tree</font></b>结构图:
b. <b><font color="#2196f3">B+Tree</font></b>结构图:
3、<b><font color="#2196f3">B+Tree叶子节点包含所有索引元素</font></b>,而<b><font color="#4caf50">B-Tree所有节点包含所有索引元素</font></b>,差异如下图:
a. <b><font color="#4caf50">B-Tree</font></b>结构图:
b. <b><font color="#2196f3">B+Tree</font></b>结构图:
4、<b><font color="#2196f3">B+Tree叶子节点之间使用双向指针连接</font></b>,而B-Tree<b style="color: rgb(76, 175, 80);">节点之间没有使用指针连接</b><font color="#000000">,</font><b style=""><font color="#f44336">差异如下</font></b><font color="#000000">图:</font>
a. <b><font color="#4caf50">B-Tree</font></b>结构图:
b. <b><font color="#2196f3">B+Tree</font></b>结构图:
<b><font color="#388e3c">Mysql索引底层数据结构采用是</font><font color="#2196f3">MySQL改造后的B+Tree结构</font></b>
<b>Hash表</b>
<b><font color="#2196f3">Hash表</font></b>结构:
Hash表示意图:
<b style="color: rgb(33, 150, 243);">Hash表</b><font color="#000000">特征</font>:
对索引的key进行<b><font color="#2196f3">一次hash计算</font></b>就可以<b><font color="#2196f3">定位出</font></b><font color="#2196f3"><b>数据</b></font><b><font color="#2196f3">存储的位置</font></b><br>
很多时候<b><font color="#2196f3">Hash</font></b>索引要比<b><font color="#4caf50">B+Tree</font></b>索引<b style=""><font color="#2196f3">更高效</font></b><br>
<b><font color="#2196f3">仅能满足 “=”,“IN”</font></b>,<b><font color="#e57373">不支持范围查询</font></b><br>
<b><font color="#2196f3">Hash</font><font color="#e57373">存在冲突问题</font></b><br>
与<b><font color="#4caf50">B+Tree</font></b>相比较:
以查询<b>Col2=89</b>为例(此列<b>数据</b>为<b>非连续非顺序</b>的)
使用<b><font color="#2196f3">Hash表</font></b>结构查询,仅需要<b><font color="#2196f3">1次</font></b>即可得到结果,如下图所示:
<b><font color="#f57c00">不建议使用</font><font color="#2196f3">Hash表</font></b>结构的<b><font color="#f57c00">原因</font></b>:
a. 仅能满足 “=”,“IN”,<b><font color="#f44336">不支持范围查询</font></b>
b. <b>Hash<font color="#f44336">存在冲突问题</font></b>
<b>存储引擎索引实现</b>
<b><font color="#2196f3">MyISAM</font></b><font color="#2196f3"><b>存储引擎</b></font>索引实现
<b><font color="#2196f3">MyISAM</font></b>存储引擎产生的<b>对应的数据库文件</b>(3个)
如下图所示:
<b><font color="#2196f3">MyISAM</font><font color="#00bcd4">索引文件</font>和<font color="#00bcd4">数据文件</font>是<font color="#00bcd4">分离的</font></b>(<b>非聚集</b>)
如下图所示:
InnoDB存储引擎索引实现
<b><font color="#2196f3">InnoDB</font></b>存储引擎产生的<b>对应的数据库文件</b>(2个)
如下图所示:
<b><font color="#2196f3">InnoDB</font><font color="#00bcd4">索引文件</font>和<font color="#00bcd4">数据文件</font>是在<font color="#00bcd4">一起的</font></b>(<b>聚集</b>)
如下图所示(<b><font color="#00bcd4">主键/聚簇</font>索引结构</b>):
如下图所示(<b><font color="#00bcd4">二级/辅助</font>索引结构</b>):
由上图可知:
1、<b><font color="#2196f3">表数据文件</font></b>本身就是按<b>B+Tree</b>组织的一个<b>索引结构文件</b>
2、<b><font color="#2196f3">聚集索引</font>——叶子节点</b>包含了<b>完整的数据</b>记录
为什么建议<b><font color="#f57c00">InnoDB表必须建主键?</font></b>并且推荐<font color="#9c27b0"><b>使用整型的自增主键?</b></font>
1.1 <b style="color: rgb(245, 124, 0);">InnoDB表必须建主键</b><font color="#000000">,因<b>主键索引叶子节点</b>包含了<b>完整的数据记录</b>,所以<b>有且必须存在一个主键索引</b></font>
1.2 <b style="color: rgb(245, 124, 0);">InnoDB表必须建主键</b><font color="#000000">,a. 当<b>未设置主键</b>时MySQL底层会通过筛查把<b>数据唯一的字段</b>作为主键来<b>创建主键索引</b>,b. 当也<b>不存在</b>该<b>数据唯一列</b>时,底层会<b>新建一个rowid的虚拟字段</b>作为主键索引字段,因此更建议由我们自己来建主键</font>
2.1 <b style=""><font color="#9c27b0">推荐使用整型的主键</font></b>,是因为<b>整型</b>主键<b>占用空间小</b>,比对<b>查询效率</b>比<b>其他类型</b><font color="#9e9e9e">(其他类型需要hash后才进行比对)</font>的<b>高</b>
2.2 <b><font color="#9c27b0">推荐使用整型自增的主键</font></b>,是因为<b>索引数据结构节点中的元素</b>是<b>从左到右依次顺序递增</b>的,当<b>新增索引元素</b>时底层需要<b>比对后插入</b>且<b>可能会发生数据结构再平衡</b>操作,相对<b>自增的主键插入效率更高</b>点
为什么<b><font color="#f57c00">非主键索引</font><font color="#ff9800">结构叶子节点只存储的data是主键值?</font></b>
1. 数据一致性
2. <b>节省存储空间<font color="#ff9800">(主要原因)</font></b>
<b>索引最左前缀原理</b>
<b><font color="#2196f3">索引最左前缀原理</font></b>,主要应用于“<b><font color="#4caf50">联合索引</font></b>”。
<b><font color="#4caf50">联合索引</font></b>的底层结构:
<b><font color="#2196f3">索引最左前缀原理</font></b>的实际应用说明:
指:对以含联合索引的第一个(最左侧)的索引字段的查询有效
以<b>t_user</b>表,联合索引为 <b>KEY `idx_name_age_position` (`<font color="#00bcd4">name</font>`, `age`, `position`) USING BTREE</b> 为例:
实际应用<b><font color="#00bcd4">有效</font></b>情景:
应用1:select * from t_user where <b><font color="#00bcd4">name = 'Lilei'</font></b> and age = 30 and position = 'dev';
应用2:select * from t_user where <b><font color="#00bcd4">name = 'Lilei'</font></b> and age = 30;
应用3:select * from t_user where <font color="#00bcd4"><b>name = 'Lilei'</b> </font>and position = 'dev';
实际应用<b><strike><font color="#f44336">无效</font></strike></b>情景:
应用1:select * from t_user where age = 30 and position = 'dev';
应用2:select * from t_user where age = 30;
应用3:select * from t_user where position = 'dev';
0 条评论
下一页