这一篇文章本来应该是放在 mysql 高性能日记中的,并且其优化程度并不高,但考虑到其特殊性和原理(索引结构也在这里稍微讲一下)

一,mysql 索引结构 (B、B+树)

要问到 mysql 的索引用到什么数据结构,我相信大部分都能回答出来,没错,就是 B+ 树。那再问为什么要用 B+ 树呢,与红黑树,hash 表又分别有什么区别呢,问到这里可能就难住了一些没思考过的轻度玩家了。这里简单描述一下

B 树与红黑树的区别,有数据结构基础的同学应该可以讲出来,红黑树是平衡二叉树的一个变种,利用红黑树的 5 个特征保证其近乎平衡,记住,红黑树降低的左转右转的递归向上,但其并不是绝对平衡,但非极端情况下,我们也可以说红黑树的查询和插入都是 log2n 的时间复杂度;而 B 树可以理解为平衡 n 插树,每个数的节点并不是一个值,而是一个数组,每两个数值之间指向一个在两者之间范围的新节点,这里可以看到对于相同的数据量,B 树的高度远远小于,根据官方给出一般索引的高度不会超过 5 的高度计算,3亿的数据量仅需要每个节点 50 个数据,mysql 在每个节点的遍历也是用最快的二分查找,所以查询一个 3亿 数据量的时间复杂度仅为 5log250,算下来几乎为常数级

B 树与 hash 表的区别,hash 的查询会比 B 树更快一些,好的 hash 表甚至可以达到 1-5 次查询得到结果,但与已经是常数级的 B 树相比,并没有太大的一个优化,但 hash 的插入却很容易产生 hash 冲突,现有解决 hash 冲突的方法无不是需要耗费大量时间进行重新 hash,相较微量的查询优化,写的效率过低导致 mysql 不可能使用 hash 表作为索引结构。

mysql 的索引结构其实本质是 B 树的一个变种结构 -- B+ 树,相较 B 树,B+ 树更适用于文件型索引,其每个非叶子节点存储的只是用于索引排序的辅助数值,而真正的数据都放在叶子节点,对于 mysql 这种不仅仅存单纯的排序值,而是关系型数据的 db,当然是 B+ 树更适合作为索引结构,当然还有一个小的优化点是子节点之间是有指针连接的,加快了范围查找的速度。

,复合索引结构

对于主键索引,肯定索引结构是按一个主键的顺序组合的 B 树,但对于一个含有两个列的复合索引,它的树状结构是什么样呢?

对于复合索引 Index(A,B),B 树的排序是按 A 列的数值为第一要素,B 列的数值为第二要素进行排序,这也就是为什么我们查询语句时,条件语句必须保证最左原则才可以利用到索引

这里引入一些题外话,聚簇索引(Innodb)和非聚簇索引(myisam),因为讲到索引结构,这里引入这个话题,也是 mysql 中比较常用的两大引擎的一个区别,聚簇索引的索引的叶节点存放的直接是数据的叶节点,当使用辅助(符合)索引查询时,其叶子节点存放的是主键的值,所以通过符合索引查找非覆盖索引数据时,都会进行两次查询,并且查询主键的速度没有 myisam 的速度快;非聚簇索引指索引的叶节点存放的是数据的页数据指针,辅助索引存的同样是指针。两者各有千秋,不能说哪个好哪个坏,按业务自身选择即可

回到正题,那对于复合索引的查询是如何的过程,那如果真的想要只查 B 又想用到索引,该如何使用呢?引入我们的第三个话题

,紧凑索引与松散索引

如果不遵守最左原则,where b = xxx,就会使用紧凑索引遍历的方式,进行全表扫表。而我们如果真的有些情况,需要查出符合 B 条件但对 A 不进行限制的情况,应该如何处理,可能有些同学会新开一个独立索引仅包含 B 列,这样虽然能达到我们的目的,但难免有些多余。mysql 也是也能很好的进行跳跃松散索引扫描,只是 mysql 优化器无法自动进行,必须在查询语句中进行必要的声明。 select * from xxx where B = xxx group by A; 添加 group by 字段后,会先根据 A 索引分组后,会在每个 A 的范围内使用索引进行快速查询定位所需要的 B 列,这就叫做松散索引扫描,比新建一个索引的效率会慢 A 的 distinct 倍,但省去了新索引的消耗。

--业务程序员

mysql 松散索引与紧凑索引扫描(引入数据结构)的更多相关文章

  1. MySQL优化GROUP BY-松散索引扫描与紧凑索引扫描

    满足GROUP BY子句的最一般的方法是扫描整个表并创建一个新的临时表,表中每个组的所有行应为连续的,然后使用该临时表来找到组并应用累积函数(如果有).在某些情况中,MySQL能够做得更好,即通过索引 ...

  2. MySQL松散索引扫描与紧凑索引扫描

    什么是松散索引? 答:实际上就是当MySQL 完全利用索引扫描来实现GROUP BY 的时候,并不需要扫描所有满足条件的索引键即可完成操作得出结果. 要利用到松散索引扫描实现GROUP BY,需要至少 ...

  3. MYSQL的全表扫描,主键索引(聚集索引、第一索引),非主键索引(非聚集索引、第二索引),覆盖索引四种不同查询的分析

    文章出处:http://inter12.iteye.com/blog/1430144 MYSQL的全表扫描,主键索引(聚集索引.第一索引),非主键索引(非聚集索引.第二索引),覆盖索引四种不同查询的分 ...

  4. 高性能mysql:创建高性能的索引

    本文系阅读<高性能MySQL>,Baron Schwartz等著一书中第五章 创建高性能的索引的笔记,索引是存储引擎用于快速找到记录的一种数据结构. 索引对于良好的性能非常关键,尤其是当表 ...

  5. MySQL 优化之 index merge(索引合并)

    深入理解 index merge 是使用索引进行优化的重要基础之一.理解了 index merge 技术,我们才知道应该如何在表上建立索引. 1. 为什么会有index merge 我们的 where ...

  6. MySQL学习(二)索引与锁 --- 2019年1月

    1.Order By 是怎么工作的 MySQL做排序是一个成本比较高的操作.MySQL会为每个线程分配一个 sort_buffer 内存用于排序,该内存大小为 sort_buffer_size. 全字 ...

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

    索引是一种用于快速查询行的数据结构,就像一本书的目录就是一个索引,如果想在一本书中找到某个主题,一般会先找到对应页码.在mysql中,存储引擎用类似的方法使用索引,先在索引中找到对应值,然后根据匹配的 ...

  8. mysql索引之一:索引基础(B-Tree索引、哈希索引、聚簇索引、全文(Full-text)索引区别)(唯一索引、最左前缀索引、前缀索引、多列索引)

    没有索引时mysql是如何查询到数据的 索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点.考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储10 ...

  9. 转MySQL详解--索引

    写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点.考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储100条记录.如果没有索引,查询将 ...

随机推荐

  1. Matlab---三维视图的自动旋转

    Matlab---三维视图的自动旋转 这里给出一种格式说明: % figure % plot3(...); % xlabel('X轴'); % ylabel('Y轴'); % zlabel('Z轴') ...

  2. Map的使用及遍历方式

    Java中Map遍历的四种方式 如果同时需要key和value推荐使用entrySet(第一种): 如果只是获取key,或者value,推荐使用keySet或者values方式(第二种): 如果需要在 ...

  3. gitlab 错误处理

    用gitolite新建项目,clone后首次push,可能会出现: $ git push No refs in common and none specified; doing nothing. Pe ...

  4. R中数据的输入和数据的标注

    数据的导入 默认情况下数据导入时,字符型变量将转化为因子.若不希望转化,可设置 stringsAsFactors=FALSE 从带分隔符的文本文件中导入数据 read.table() file --& ...

  5. jQuery基础 (一)—样式篇

    jQuery的优势 jQuery有很多特性和工具方法

  6. WPF DevExpress ChartControl使用之PieChart

    饼状图要比XYDiagram要简单一点,大体上也是那些东西,没有了X.Y坐标轴,也就没有了第二坐标,要简单一点.PieChartControl.xaml <UserControl x:Class ...

  7. C# 异步编程 (12)

    异步编程重要性 C# 5.0 提供了更强大的异步编程.添加两个新的关键字 async 和 await . 使用异步编程,方法调用是在后台运行(通常在线程或任务的帮助下),并且不会阻塞调用线程. 3种不 ...

  8. scala-currying化

    scala的加里化(currying)纠结了很久.通过Scala Worksheet 可以打印很多调试信息,所以用它写了一些测试代码,帮助自己理解. object test { //一个参数列表,3个 ...

  9. Failed to start MariaDB database server. (已解决) 之前配过主从

    [root@linux-node1 /var/log/mariadb]# systemctl status mariadb.service● mariadb.service - MariaDB dat ...

  10. 题解 [BZOJ4886] 叠塔游戏

    题面 解析 这是个有趣的建图题啊. 首先我们可以发现,宽度严格递增是没什么用的. 因为实际上我们在旋转完以后, 矩形的顺序是可以随便排的. 因此只要保证宽度互不相同就行了. 然后,我们对长和宽离散化, ...