MySQL索引全解:从理论到实践,打造高效查询的指南

2025年01月大数据月报 2025年01月大数据月报,为您准备了阿里、字节、百度等大厂90多篇实践案例 阅读详情

前言

授人以鱼,不如授之以渔,授人以鱼只救一时之急,授人以渔则可解一生之需。 我一直以为,任何规范只能约束一时,要想真正的解决问题,就一定要搞清楚问题背后的道理,这是我写这篇文章的初衷,我希望开发者在按照规范或者经验去尝试使用索引解决一些问题的同时,也能想清楚这样做是不是对于所有的场景都合适,有没有什么缺点?要知道,如果一味的按照规范去执行,就好像是在按别人的脚码去买鞋,买的是对的,但却不适合自己,规范和经验只是提供了一种指导和参考,而真正的解决方案应该根据实际情况进行量身定制,而本文就是要让大家拥有量身定制的能力。

索引的数据结构

这一节先从索引的数据结构开始讲起,如果说数学是一切科学的基础,那数据结构和算法就是计算机程序的基础,解决同样的问题,用合适的数据结构和算法可能只需要几分钟,而不合适的可能需要好几年,这是量级上的巨大差异。 对于解决数据检索问题的时间复杂度而言,哈希索引通常被认为是最快的方法。然而实际应用场景往往是复杂多变的,它要解决的更多是软件工程问题,而非理论科学问题,所以,仅仅关注算法的时间复杂度是不够的,还要结合实际的应用场景,综合考虑各种因素,以便选择最适合的数据索引方案。

哈希表

我们先来简单了解一下哈希表的数据结构,哈希表是一种以(key,value)形式存储的数据结构,通过哈希函数的方式找到关键字在索引中的位置,使其能支持快速的查找、插入和删除。 哈希表实现简单且检索效率也非常高,像Redis这样的内存数据库就有大量用到了哈希表作为其数据检索的索引。

下图主要展示了Redis中哈希表的数据结构:

那为什么在MySQL中没有大量应用呢?(MySQL目前只有memory存储引擎支持指定使用哈希索引)

结合MySQL实际要解决的问题,主要有如下几个原因:

  1. 哈希索引无法支持范围查询,通过哈希函数定位到的索引位置是随机的,物理位置上相邻的两个数在逻辑上并没有任何关系,所以像大于、小于这样的范围查询就无法利用哈希索引来提高效率了。

  2. 无法支持排序,道理和前一条中解释的是一样的。

  3. 只能支持完整索引值快速查询,不能加速类似右模糊这样的查询,因为哈希函数计算的是完整的索引值。

上述3个问题都是平常业务中非常常见的场景,因此如果不能满足,则就需要考虑是否还有其他更合适的数据结构了。

这里额外补充一点:InnoDB引擎有一个特殊的能力,叫做自适应哈希索引,也就是当某些索引值使用的非常频繁时,InnoDB会在内存中基于这个值再构建一个哈希索引,这样就能利用哈希索引的优势快速定位,不过这个行为对于客户端来说是不可调整的,客户端能做的就是决定开启还是关闭这个能力(由innodb_adaptive_hash_index参数控制,默认为开启)。

有序数组

有序数组是可以高效的支持范围查询、排序等操作,因为是有序的,所以可以利用二分查找来快速定位元素位置,这样看来,有序数组无论是在单键查询还是范围查询、排序甚至是模糊查询,都是非常高效的,所以,如果只需要满足数据检索的需求,有序数组已经非常合适了。

二分查找:

不过有序数组必须还得保证当有数据插入、修改或者删除时依然能保证其有序性,这通常需要较高的操作成本,变更影响到的数据越靠前,性能消耗就越大。

插入数据:

所以,对于需要经常插入、删除、修改等操作的数据库来说,有序数组显然也不合适。

树

有没有一种数据结构能够同时解决数据检索和数据更新的问题呢?答案就是:平衡搜索树,实际应用中常见的平衡搜索树有AVL树和红黑树,平衡搜索树会在进行插入和删除操作时,通过调整自身的结构以保持树的高度平衡,从而保证搜索、插入和删除操作的时间复杂度都是O(logN)。

AVL树

红黑树

截止到目前为止,平衡搜索树基本上已经解决了前面两种数据结构遇到的所有问题,实际上Innodb存储引擎选择的也就是平衡搜索树,只不过这个平衡搜索树既不是AVL树也不是红黑树,而是B+ Trees,而选择B+ Trees的理由只有一个:更适合磁盘存储。

详细聊聊B+ Trees

上节中,我们介绍了几种常见的数据检索相关的数据结构,并对其优劣势进行了简单的分析,最终发现平衡搜索树是面对此类问题场景中不错的选择,同时在小节文章最后,也提到了InnoDB存储引擎最终是选择了B+ Trees这样的平衡搜索树来作为其索引的底层数据结构,因此接下来本小节,我们就来了解一下B+ Trees,以及它是如何解决实际应用场景中的问题,最终让InnoDB选择它?

B+ Trees三大杀器

B+ Trees一定是软件工程的产物,它的设计与实现是面向特定应用场景的,它更加注重应用在这些场景中的可行性、稳定性以及运行效果,而最能说明这一点的核心我认为主要体现在下面三个设计中:

1. 树的度(宽度)可以很大

AVL树和红黑树共同存在的一个问题就是他们都是二叉树,无论怎样平衡在解决树的深度问题上的能力都非常的有限,而在B+ Trees(注:后续我们提到的B+ Trees都是指InnoDB中的实现)中,每个节点(InnoDB中支持对此大小进行调整,参数为:innodb_page_size)默认的大小是16KB。假设我们索引的字段是int类型,也就是4个字节,那么也就意味着我们一次性可以读取4096条索引值到内存中(16KB/4byte=4096条,实际情况还要考虑指针等记录所占用的空间)。 对于一个度为:7的树来说,存储22个元素只需要2层,而如果是二叉树则至少需要5层。

所以,解决了树的宽度问题,自然也就解决了树的深度问题。

既然这样,是不是可以直接调整innodb_page_size的大小,比如innodb_page_size支持你调整到32KB或者64KB,其实之所以默认是16KB,主要是因为当前主流的磁盘设置,扇区大小就是16KB,保持页的大小与扇区大小一致,可以最大限度的减少将未更改的数据重写到磁盘,此外如果是经常用于频繁写入和读取的场景,较小的page_size也可以减少单个节点被频繁重写到磁盘的情况。

2. 叶子节点存储数据

聚簇索引

叶子节点存储数据这个设计,还有个专门的词语用来描述它:聚簇索引。 聚簇索引并不是一种单独的索引类型,而是一种数据存储的方式,聚簇指的就是数据行和索引值存储在一起。

聚簇索引的优点
  1. 因为数据行和索引键值存放在一起,因此在根据索引找到对应数据页之后,即可直接从该数据页中取出所需要的数据并返回,如果没有使用聚簇索引,则至少还需要再进行一次磁盘I/O。

  2. 查询时能使用覆盖索引也是建立在聚簇索引的前提之上才能实现的。

聚簇索引的缺点
  1. 因为需要存储数据行,因此在数据插入和更新时,聚簇索引的设计要明显慢于非聚簇索引,尤其是随机插入或者更新时更为明显。

  2. 由于每个二级索引都会记录主键索引的键值,因此不但会占用更多的存储空间,也会在数据行删除和插入时更加费时。

  3. 由于数据行保存在主键索引的叶子节点上,因此每次根据二级索引查询时,二级索引如果又不是完全覆盖,则还需要再回到主键索引上查询一次,这个过程我们也称为回表查询。

聚簇索引与非聚簇索引对比

主键索引和二级索引

对于主键索引与二级索引来说,叶子节点存储的数据还有点不一样,如果是主键索引,叶子节点存储的就是整行数据,而如果是二级索引,叶子节点存储的则是主键ID和索引列数据。

二级索引

类似这样的查询select id from t where phone = ?;因为二级索引的叶子节点除了会记录索引内容本身之外,还会记录主键索引的值,因此如果只是查询id,则直接通过扫描二级索引即可完成。 检索数据至少需要经历2次磁盘I/O

主键索引

但如果是id和name都需要查询:select id, name from t where phone = ?;就会先通过phone这个二级索引定位到主键id,然后再用主键id去主键索引中查找一次,最终才能将id和name一起返回。

检索数据至少需要经历4次磁盘I/O(二级索引和主键索引分别2次)

最后,我们再来想想为什么数据只会保留在叶子节点上?

这其实也是B+ Trees和B Trees的一个重要区别,如果将数据也保留在非叶子节点上会有什么问题呢? 问题一:它可能会致使子树节点中存储的数据量急剧减少,导致树的高度增加。 问题二:查询可能出现时快时慢,让系统看起来不是很稳定,运气好可能在树的第二层就拿到了数据(1次磁盘I/O),运气不好就不好说了(因为越往下覆盖的数据就越多,所以可能大多数时候你的运气都会很不好)。 所以,最终的结论就是,数据只保存在叶子节点上可以最大限度的让非叶子节点多存储一些数据,从而避免引发树的深度问题。

3. 叶子节点双向指针记录

这个设计是B+ Trees和B Trees另一个重要的区别,双向指针的记录,主要是为了更好的支持范围查询,通过指针的记录,叶子节点之间可以直接顺序遍历到,而不需要再从根节点走下来。

比如:要查询小于等于17的数据。 如果没有指针,那就只能这样查找,需要经过12次查找。

有了指针,只需要经过7次查找。

至此,我们已经介绍完了B+ Trees的三大杀器,我相信你应该也对B+ Trees有了基本的了解,后面的几小节,我们基本上就会围绕在实际应用中如何遵从并利用这些设计来提升查询效率。 如果你现在觉得这些概念还有些复杂,不能完全理解也没关系,这本身就需要一定的时间,当然,后面的一些实际应用也会反复应用到这些设计,到时候,你再结合本节内容来理解,那么我相信,这些概念就会变得越来越清晰。

覆盖索引

本节,我们先来介绍一个非常好用的优化手段,它能够极大地提高查询的性能:覆盖索引。 覆盖索引并不是一种单独的索引类型,准确的说它只是一种利用数据存储在叶子节点上的优化行为。

举个例子

前面我们提到过,当执行这段select id from t where phone = ?;查询时,因为phone索引本身就记录了主键id的值,所以省去了再去主键索引中查询整行数据的过程,从而提升了查询效率。

也就是说,如果查询所需要的列信息,本身在二级索引的叶子节点中就已经全部包含了,那么像这样的查询我们就称为:覆盖索引查询。

如何利用覆盖索引

要想利用覆盖索引的特性,一般我们会通过两种方式来实现,一种就是在建立索引时考虑,一种就是在执行查询时考虑,下面我们可以分别对这两种情况进行分析。

建立索引时考虑

还是前面的案例select id, name from t where phone = ?;也许在你的业务场景中并不存在直接通过phone和name过滤查询数据行信息的情况,所以你觉得没有必要为name字段建立索引,但如果发现有大量的根据phone查询name的需求,那么在这样的情况下,也是可以考虑建立phone和name联合索引的,这样一来就可以利用覆盖索引来提高查询效率了。

查询时考虑

常见的案例比如:深度分页查询。 比如按照每页查询10条,查询第1001页:select * from page_test LIMIT 10000,10;利用覆盖索引过滤部分结果集:select * from page_test a, (select id from page_test LIMIT 10000,10) b where a.id = b.id;

建立索引的原则

建立索引的原则,主要指的是什么情况下应该建索引,在哪些列上建索引,建什么样的索引,建多少索引等方面,这些问题应该是日常开发中最常见的,但凡建一张表就需要考虑上述几个问题。

在哪些列上建索引?

首先,索引列最好要有比较高的区分度,因为只有足够高的区分度才能更好的体现出索引的优势。 可以通过执行show index from table;命令,得到指定表索引的大致信息,其中有一个关键列Cardinality,其表示了该索引列不重复值的个数,因此该值当然越接近表的总记录数越好。

不过,这个统计并不是100%准确的,如果你遇到过MySQL选错索引的情况,很有可能就是因为这个统计有误导致的,后面会单独对这个问题进行分析,现在你只要知道有这样一个参考值即可。

其次,一般就是我们常说的涉及到where、group by、order by等查询情况时需要考虑建立索引,但前面在介绍覆盖索引时也提到,要注意利用覆盖索引的能力来加速查询,也是不错的选择。

最后,有一点比较重要,要尽量避免在频繁更新的列上建立索引,因为每一次更新都需要对索引的存储进行维护,尤其是数据页的分裂与合并将会带来比较大的性能消耗。

建什么样的索引?

按索引的建立方式可以分为:主键索引、唯一索引、二级索引、联合索引、全文索引、前缀索引

主键索引

自增主键与业务主键

数据表的主键到底是应该用自增还是直接用业务主键,比如数据表中记录的订单号,本身就必须是唯一的,因此是否可以直接作为数据表的主键? 关于这一点,在大多数情况下,还是建议使用自增主键,这样做的原因主要是因为自增主键通常空间占用更少(每个二级索引都会额外记录主键索引的值),以及自增的有序性保证也可以避免数据页的分裂问题。当然直接使用业务主键作为索引可以在查询该业务字段时减少一次回表的过程,比如:像这样的查询select order_id from t where create_time > ?如果order_id是主键,则直接建立create_time索引即可,否则通常需要建立create_time和order_id的联合索引。

二级索引与唯一索引的选择

二级索引和唯一索引是两种常见的索引类型,它们各有优缺点。 二级索引不要求索引值在索引记录中只能有一个,这意味着在同一个索引中可以有多个相同的索引值。而唯一索引则要求每个索引值必须唯一,也就是说在同一个索引中每个索引值只能出现一次。这种简单的区别却带来了不同的查询和更新处理方式,是在选择时需要考虑的主要因素。 接下来,我们就来对比一下两种索引在查询和更新上的差异性。

查询

我们先来看看查询,对于唯一索引来说,很明显,一旦查询到数据后,即可直接返回。而如果是二级索引,则需要继续查找当前数据的下一条记录,当下一条记录不能匹配时则可返回。 看起来二级索引因为不能确认当前查询到的结果是否是唯一的,所以需要额外的查询一次下一条记录,但实际上我们应该考虑到由于数据是按页加载到内存中的,因此绝大多数情况下,所谓的获取下一条记录并进行判断只是一次内存中的寻址和简单的计算而已,这样的性能差异几乎是可以忽略不计的。 当然,也有比较特殊的情况,就是匹配到的数据刚好是当前数据页中的最后一条记录,那么再查询下一条记录时则有可能因为下一条记录所在的数据页不在内存中,而需要进行一次从磁盘加载到内存中的操作了,不过,对于一个数据页通常能记录上千条索引值来说,这样的概率也是非常小的。 例如这样的查询select * from t where x = 2二级索引会查到下一页。

基于上面的分析,我们可以发现对于查询操作来说,二级索引与唯一索引并没有明显的性能差异。

更新

我们再来对比一下两种索引的更新操作。不过,在这之前需要先简单介绍一下change buffer。

什么是change buffer?

为了加快数据更新的速度,在InnoDB中,每次数据更新实际上都会先查询当前要更新的数据页是否已经加载到内存中了,如果是,则直接更新内存中的数据页即可,如果不是,则会先将本次更新记录到change buffer中,这样则能免去一次从磁盘加载数据页的过程。

change buffer的merge

更新记录当然不会一直保留在change buffer中,最终还是需要写到数据页的,change buffer写数据页的过程也被称为change buffer的merge过程,通常有如下三种情况会触发change buffer的merge操作:

  1. 当前数据页被访问了。

  2. 后台定时merge。

  3. 数据库关闭。

change buffer会丢失吗?

当然,也许你也注意到了,如果在change buffer merge之前数据库宕机了,那change buffer中记录的信息岂不是全部都丢失了?这里需要说明一下,change buffer中记录的操作实际上也会记录在redo log里,并随之一起写磁盘,而redo log保证了数据不会丢失。

change buffer也有不适用的场景

change buffer更适合有频繁数据写入的情况,比如批量插入,或者说适合写完以后不会立刻读的情况,反过来,如果写完以后,立刻就要读,那就会触发merge,这样反而多了一次维护change buffer的过程。

再看更新

说了这么多,现在我们可以回到更新这个问题上来了,我们可以分两种情况进行分析:

第一种,如果数据页已经在内存中了,那么对于唯一索引来说,需要先判断前一条和后一条记录是否重复,如果不重复则直接更新即可,对于二级索引来说,无需判断直接更新即可。就和查询时的校验一样,这样的操作性能差异并不大。 第二种,如果数据页不在内存中,那么对于唯一索引来说,必须先将数据页加载到内存中,并进行判断,而对于二级索引来说,则不需要,只要直接写change buffer即可,也就真正利用了change buffer的能力。

结合查询和更新两大场景来看,在大多数情况下二级索引实际上比唯一索引更合适,不过,我们经常也为了解决幂等性问题,通过建立唯一索引来作为最后一道天然的屏障,如果业务上有这样的需要,那就建立唯一索引,不必在意change buffer的问题。

联合索引

如果明确有多个列会频繁组合在一起查询时,那么为这些列建立联合索引则会比较高效,就好比原本你需要到多个索引文件中挨个检索的情况,现在只需要在一个索引文件中就能完成。

除了你本身已经识别出来的情况,通常如果你在执行计划Extra列中看到比如:Using union 、Using intersect等关键字时就是在提醒你应该考虑建立联合索引了。

联合索引要注意什么?

  1. 遵守最左匹配原则。

  2. 区分度高的尽量放在最左边(注意:这不是绝对,以后在聊到SQL优化时会提到这一点)。

  3. 联合索引列数不宜过多,很明显,列数过多就像字段长度太长一样,从对磁盘和内存的使用来说,都不是好的选择。

全文索引

全文索引是一种特殊的索引,它主要是用来在一段文本中查找关键字,而不是直接比较索引中的值,它和前面几类索引完全不一样,全文索引更类似于搜索引擎做的事,使用时你得关心停用词、词干等,而不是简单的where查询。 不过全文索引和前面这些索引并不冲突,也就是说你可以在同一个列上同时创建二级索引和全文索引。

前缀索引

因为索引本身也是需要存储的,所以索引长度首先影响的就是存储空间(不局限于磁盘上的存储,也关系到内存中的数据页能一次性加载多少索引键值)。

一般如果要在一些前缀重复度较高的列上加索引时(比如城市地址、有固定前缀规则的编号等),可以考虑使用前缀索引,这样有时候不但可以提升索引性能,还能节省索引空间。

前缀索引最关键的就是找到一个合适的索引长度,兼顾索引的选择性以保证查询效率,索引的选择性指的是不重复的索引值和数据表的总记录的比值,选择性越高查询效率也就越高,比如唯一索引的选择性就是1。

关于选择性的计算

下面这个语句是一个索引选择性计算常用的查询方式:select count(distinct left(索引列,索引长度))/count(*) from table;

SELECT count(DISTINCT LEFT(order_no, 20)) / count(*) AS '20', count(DISTINCT LEFT(order_no, 22)) / count(*) AS '22', count(DISTINCT LEFT(order_no, 24)) / count(*) AS '24', count(DISTINCT LEFT(order_no, 26)) / count(*) AS '26', count(DISTINCT LEFT(order_no, 28)) / count(*) AS '28', count(DISTINCT LEFT(order_no, 30)) / count(*) AS '30', count(DISTINCT LEFT(order_no, 32)) / count(*) AS '32' FROM test;

order_no字段在设置时长度为32,可以看出长度从26开始,区分度已经接近1,所以此时再增加长度的性价比已经不高了。

使用前缀索引值得注意的地方

  1. 由于数据是不断变化的,因此之前计算得到的选择性可能因为数据的变化而变化,最终导致性能越来越差。

  2. 选择性的计算也许并不够准确,比如从上面的结果的来看,长度26已经比较合适了,但实际上这只是一个平均值,你要确保数据分布的是否足够均匀,否则你可能会掉入陷阱。

  3. 一旦使用了前缀索引你就失去了order by、group by以及覆盖索引等提升查询性能的能力了。

索引有序性

我们再来额外谈谈关于索引的有序性问题,为什么我们都说要尽量避免使用像UUID这样的数值作为聚簇索引,除了他本身比较占用空间之外,还有一个更重要的原因就是UUID是无序的,无序性会带来更严重的问题,它使得聚簇索引的插入变得完全随机,没有任何聚集特性可言,也将导致很多围绕程序局部性原理的设计变得无效。

建议自己先试验一下使用自增主键,与使用UUID作为主键两种方式在数据插入上的性能差异,尤其是当索引大小超过服务器内存时。

如果索引值是顺序的,那么当一个数据页满了以后(实际上不会完全满,InnoDB默认的最大填充因子是页大小的15/16),只需要将数据插入下一个新页即可。 如果索引值是随机的,那么就无法简单的把数据插入最后,InnoDB得先为数据找到合适的位置,这会带来以下几个问题:

  1. 可能目标数据页已经刷到磁盘上了,那么InnoDB就必须先将数据页从磁盘加载到内存中,这将会产生大量随机I/O。

  2. 因为数据的顺序是随机的,所以可能会产生大量的页分裂操作,页分裂会导致需要移动大量的数据。

  3. 页分裂过多的结果又会造成数据页变得稀疏,最终可能又会触发数据页合并,数据页合并又会导致需要移动大量的数据。

一棵被无序插入的索引树

插入:6,第一个数据页变稀疏了,只记录1、2、3,并且涉及到了3个数据页的改动。

使用optimize table命令可以重新优化数据页的使用情况。

建立多少索引?

显然,索引的数量并不是越多越好,这是因为索引的增加会对数据库的写入性能产生不利影响,每一个索引都会有一份独立的存储数据,索引越多也就意味着同时要维护的索引文件越多,这会对系统造成不小的消耗,因此,索引的数量需要控制在合理的范围,以便最大化提高查询性能,并同时减少索引维护的成本。 此外,索引越多也意味着要存储的内容越多,就需要更多的磁盘空间来存储。

如果是非聚簇索引还会有这个问题吗?

所以,我认为建多少索引主要还是需要结合实际的业务场景来定夺,你只要清楚的了解其中的利弊就可以了。

不过有一类场景可以提醒一下,就是类似归档表这样的数据表,有时这样的表可能并不需要像原表一样为了满足业务查询建立许多索引。减少一些不必要的索引,不但能够加快归档的速度,同时还能减少存储的空间。

为什么会选错索引?

不知道你有没有遇到过由于MySQL选错索引而导致查询变慢的情况,并且有时候选错的情况看起来非常的傻,让人不能理解,如此智能的优化器为什么会犯这么简单的错误?好了,本节我们就是来搞清楚这个问题的。 首先,不得不说,绝大多数情况下你不要以为自己比优化器要厉害,优化器已经完成了上百个优化项,下面列举了几个优化类型:

  1. 把取最大、最小当作一个常数条件,直接获取索引的第一条或者最后一条记录。

  2. 因为id是表的主键,因此优化器能确定最多只会返回一条数据,所以where条件可以被当作常量类型处理。

  3. 还有很多语句上的改写,比如: 1=1 and x > 1会被直接改为 x > 1,(a < b and b = c)and a = 5会被改为b > 5 and b = c and a = 5

优化器成本模型

MySQL的优化器使用的是一种基于成本模型的方法,用于评估和优化查询性能。其中一个重要的成本指标就是本次查询需要扫描的行数。这个指标对于优化器作出正确的决策非常关键,它直接影响了对于查询成本的评估。如果统计不准确,优化器就可能会产生错误的结果。

前面我们也提到过可以通过show index from table;得到一个索引的大致信息,其中有一个关键列Cardinality,其表示了该索引列不重复值的个数(非精确统计),因此该值当然越接近表的总记录数越好。

现在我们有必要了解一下这个Cardinality是怎么得来的,实际上,InnoDB引擎是通过抽样的方式来计算这个基数信息的,首先读取少量的数据页(具体数据量由innodb_stats_sample_pages来设置),统计这些数据页上的数值,得到一个平均值,然后乘以索引总共的数据页,就得到了这样一个基数。

当然,数据表是会变化的,所以索引的统计信息也必须跟着变,触发重新统计的条件大概有下面几种:

  1. 超过一定数量的数据行产生了变化。

  2. 执行analyze table、show table status、show index等这样的命令。

除了这个索引统计信息不准确会导致选择错误之外,还有如下一些情况可能会导致MySQL优化器选错执行计划:

  1. 成本指标并不完全等同于运行时的实际成本,例如执行计划可能预估需要读取更多的页面,但实际读取时可能成本却很低,因为如果读取的页都是顺序读取或都已经在内存中的话,那么它的实际访问成本将降低,而优化器并不知道哪些页在内存中,哪些在磁盘上。

  2. 基于成本模型并不意味着执行的时间就是最快的。

  3. 用户自定义的函数或者执行存储过程这些优化器并不会考虑其成本,因为这些不受其控制。

索引的优点

最后我们总结一下索引的优点,索引不仅可以提高数据定位的速度,而且还可以提高数据排序,数据分组的速度,总的来说索引主要是通过以下两种方式来提升性能的:

  1. 减少扫描数据行的数量。

  2. 将随机I/O变为顺序I/O。 对于提高数据检索效率的通用思路,一般都是以上述两个方面为基础的。一方面是通过优化索引设计来实现,选择合适的数据结构和算法,另一方面则是在了解其实现原理之后选择合适的查询语句以及优化技巧,以确保索引的效果最大化。

总之,通过优化索引设计和合理运用查询语句,可以大大提高数据检索效率,实现更加高效、准确、快速的数据检索服务。

【信息科学与工程学】【数据科学】数据科学领域-第十一篇 数据集成算法01 ​​降低维护成本​​:通过抽象通用流程(如),当需要修改故障注入逻辑(如更换混沌工具)时,只需修改一处代码,无需修改所有测试用例;​​提升扩展性​​:通过参数化故障场景(如),可快速生成新的故障用例(如针对新服务的延迟故障),适应系统迭代需求;​​增强场景真实性​​:通过组合混沌操作(如),模拟真实生产环境中的复杂故障链(如“网络延迟+服务宕机”),更准确地验证系统韧性;​​提高分析效率​​:通过自动化结果分析(如),快速获取MTTR、错误率等关键指标,减少人工分析时间。 阅读详情

相关推荐

打造双端视频播放APP:苹果CMS系统源码与教程全解

苹果CMS,即Apple Content Management System,是一款专为影视类网站构建的CMS(内容管理系统)。它起源于中国,经历数年的发展,已经成长为国内影视类网站建设的热门选择。因其方便的安装、丰富的主题和插件,以及对新媒体内容的高度支持,受到众多影视爱好者和网站运营者的青睐。苹果CMS系统的特色功能包括:- 多种视频点播功能- 自动采集、更新影视资源- 良好的用户评论互动系统- 强大的后台统计分析工具。

weixin_35987118的博客 1180

MySQL如何高效查询

在 InnoDB 中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表。,InnoDB 使用了 B+ 树索引模型,所以数据都是存储在 B+ 树中的。 每一个索引在 InnoDB 里面对应一棵 B+ 树。B+树的特性你可能需要单独了解一下,叶子节点有序存储数据,非叶子节点存储索引值。

wangminlalala的博客 859

SpringBoot+Vue+MyBatis实战:小说阅读管理系统开发全解

在Java Web开发中,构建一个功能完善的内容管理系统通常需要处理用户认证、数据检索、状态同步等复杂需求。以SpringBoot为核心搭建RESTful API,配合MyBatis的灵活动态SQL实现多条件组合查询与分页,再结合Vue的组件化响应式特性打造流畅的SPA界面,是当前全栈开发中成熟且高效的技术组合。这种架构不仅简化了前后端联调流程,还能通过Docker快速部署至Linux服务器,显著提升开发与运维效率。本文以小说阅读管理系统为实践载体,完整展示了从数据库设计、后端接口开发、前端阅读器交互到容器

weixin_35639680的博客 226

15个高效的MySQL数据库查询小技巧

介绍15个提高MySQL数据库性能的常用技巧。

u013643074的博客 1542

PIN限幅二极管在接收机中的应用

本文介绍了接收机保护限幅器的工作原理及应用,重点阐述了PIN二极管在雷达收发机中的关键作用。文章指出,限幅器能有效保护接收机灵敏元件免受大功率信号损害,主要通过反射而非耗散功率来实现保护功能。文章详细分析了PIN二极管的层结构特性及其阻抗变化机制,解释了多级限幅器的设计原理(包括清理级和粗限幅器的配合使用),并介绍了通过添加检波二极管降低阈值水平的方法。最后指出,实际应用中限幅器通常采用3级或更少的设计。

weixin_49761275的博客 2370

ZynqMP双核通信避坑指南:Linux驱动+裸机固件协同开发实录

本文详细解析了Xilinx ZynqMP芯片中APU与RPU双核通信的技术实现,重点介绍了通过IPI中断实现Linux驱动与裸机固件协同开发的实战经验。内容涵盖硬件寄存器配置、Linux驱动开发、RPU裸机程序编写以及双核调试技巧,为开发者提供了一套完整的工程化解决方案,帮助规避常见开发陷阱。

weixin_29168153的博客 126

mysql的高级查询语句

数据库是用来存储数据,更新,查询数据的工具,而查询数据是一个数据库最为核心的功能,数据库是用来承载信息,而信息是用来分析和查看的。所以掌握更为精细化的查询方式是很有必要的。本文将围绕数据的高级查询语句展开。为了下面查询语句的运用,事先准备了两张表,后续也会根据查询功能的运用会对表进行一些变动,或则创建新表:););视图能否插入数据,要看情况而定:1)如果视图表是两个表的连接查询(比如视图的A字段来自A表,B字段来自B表,数据是无法插入的)。因为表结构和原表不一致。

qq_62462797的博客 2660

台积电技术研发实力

台积电技术研发实力 台积电在半导体行业的地位毋庸置疑。他们究竟有多强大,大部分读者了解得可能非常片面。从最新公布的2019年财报里,看看台积电的真正实力。 一、台积电在市场上的地位 根据公司财报,台积公司在先进制程技术、特殊制程技术,以及先进封装技术的发展上持续领先全球集成电路制造服务领域,2019年的市场占有率为52%。台积公司总体营收以地区划分(主要依据客户营运总部所在地),来自北美市场的营收占台积公司总体营收的60%、日本与中国大陆以外的亚太市场占9%、中国大陆市场占20%、欧洲、中东及非洲市场占6

吴建明wujianming_110117 1900

【③MySQL 数据查询】:提高查询的效率

【MySQL 数据查询】: 基本、分组、排序、聚合、分页、条件查询详解

热爱编程的小K的博客 5291

CSI Tools 工具的安装 Intel 5300 + Ubuntu14.04

在 ubuntu14 系统上面安装 CSI Tools,2020最新教程,亲测可用,只要保证和我做法一致绝对可以安装好。

WS的小屋 1万+

【深圳】IBM V3500存储维修 更换控制器故障

今天给大家分享的是深圳.福田区一个电商客户公司一台IBM Storwize v3500存储控制器故障从远程诊断 收集日志 分析结果的实际案例,如图所示通过存储管理口登陆进去后直接看到少了一个控制器,经过工程师分析日志后判定为该控制器损坏,接下来更换控制器配件,标准套件的控制器不带子卡和电池,所以需要把故障控制器上的子卡和电池拆下来装到新控制器上,这个电池拆还需要点技巧,接着把新的控制器插回V3500主机,等待大约十分钟后,新控制器指示灯全绿,管理界面看到节点已联机;冠峰科技-爱科技爱分享。

OuYangYuXi的博客 4574

提高查询效率:MySQL高级查询技巧

MySQL是一个高度优化的数据库管理系统,但是在处理大量数据时,它可能会遇到一些性能问题。这些问题通常可以通过查询优化来解决。选择合适的数据类型索引优化查询语句。

博客简介 569

Clion编译stm32cube初始化工程时non constant or forward reference address expression for section .ARM.extab报错

相信应该有同学在看了稚晖君关于clion开发stm32的文章之后也想在自己PC上实现“优雅の嵌入式开发”遇到和我类似的问题。他的文章是22年写的,我个人猜测应当是版本更新导致的不适配。意思就是说 READONLY 只能在gcc11以后的版本中使用,gcc10及以前的版本将无法正确识别,也就有如下错误。或者就可以将gcc升级至最新的版本。记得在clion工具链中修改c,cpp编译器的位置。可以将文本括号中的 READONLY 全部删除。当时由于没有注意到这行注释导致在这里卡了好久。

2301_77256849的博客 2510

MySQL查询原理与优化

上一篇文章中(MySQL索引全解:从理论到实践,打造高效查询的指南),详细介绍了索引相关的内容,理解这部分知识对于实现高性能的查询来说必不可少,但这并不是全部,你还需要了解MySQL的查询流程,以及一些其他相关的查询机制,这样才能确保你不会写出一些性能糟糕的查询语句。所以,本篇文章就针对MySQL查询相关的内容进行介绍,包含:执行查询的过程、查询消耗的关键指标、查询的优化等,通过这些内容希望能够帮助你明白一些执行较慢的查询产生的原因,以及如何才能避开它们。从上一篇文章。

自律使我自由 583

材料带隙预测(图神经网络)(⭐⭐)—— 用晶体图网络预测钙钛矿材料的能带隙,加速光伏材料筛选。技术栈:CGCNN、MEGNet、Materials Project数据集

钙钛矿太阳能电池以其高效率、低成本的优势迅速崛起,但传统“试错法”材料筛选效率极低,严重制约了光伏技术的迭代速度。近年来,基于图神经网络的材料带隙预测方法,特别是晶体图神经网络(CGCNN)和材料图网络(MEGNet),为这一问题提供了革命性的解决方案。本文系统梳理了材料带隙预测从传统计算到深度学习的演进历程,深入剖析了CGCNN与MEGNet的架构设计、数学原理及创新机制,详细阐述了Materials Project数据集的构建、特征工程与处理策略。

2201_76125393的博客 47

【RK3399 Ubuntu】基于rk3399的lxde的lubuntu桌面移植适配记录之第二步:最基本Ubuntu根文件系统的相关常用工具完善

文章目录1.使能系统网络管理服务1.1 安装驱动modules管理工具1.2 使能网络服务2.终端自动补全命令功能3.安装ssh服务4.安装系统信息查看工具5.安装resize工具6.安装lrzsz工具7.使能rc.local服务7.1 修改服务Install块7.2 使能rc.local.service服务7.3 添加执行脚本且赋予执行权限 续接上文,本文主要完善前面已经制作好的rootfs 1.使能系统网络管理服务 1.1 安装驱动modules管理工具 apt-get install kmod 1.

wang 恒 的博客 1385

Navicat 模式设计全解:解决数据库开发 3 大核心痛点

📺 欢迎观看本期视频!在数据库开发过程中,你是否被繁琐的 SQL 编写、结构不一致、多库兼容难等问题困扰?本期视频将为你讲解,Navicat 如何通过强大的模式设计功能,针对性解决这些痛点,助力你更高效地构建、管理和优化数据库结构。

Navicat 官方账号 460

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

【LangChain】 实战指南:从模型定义到工具调用与实时天气查询实战

随着大语言模型(LLM)的迅速发展,如何将大模型的能力无缝接入实际应用成为了开发者最关注的问题。LangChain 作为目前最流行的 LLM 开发框架,通过封装模型抽象、提示词模板、链式调用以及工具扩展等功能,极大地降低了大模型应用的开发门槛。 在实际开发中,单一的模型对话远远无法满足复杂业务需求。大语言模型存在知识库滞后、无法获取实时信息等局限,而工具调用(Tool Calling / Function Calling)正是让 LLM 连接外部真实世界的钥匙。 本文将循序渐进地介绍 LangChain

心向往之,行必能至 4106

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

mysql limit优化_不懂SQL优化?那你就OUT了 --- limit

这篇我们将讨论一下limit的优化。如果我们只需要结果集中指定的行数,那么可以在查询中使用LIMIT子句,而不是获取整个结果集并丢弃额外的数据。语法:select 列名列表 from 表名 limit row_count. (参数一:返回记录行数目)或则select 列名列表 from 表名 limit offset(参数一:返回记录行的偏移量),row_count(参数二:返回记录行的数...

weixin_39732991的博客 323

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

MySQL性能优化:十个提升查询效率的技巧

优化MySQL的效率对于提高应用程序的性能至关重要。通过合理使用索引、优化查询语句、限制结果集大小、批量插入和更新等技巧,可以显著提升MySQL的查询和操作效率。此外,使用连接池、避免过多的触发器和存储过程,以及合理使用缓存等技术也可以进一步优化数据库性能。定期备份和优化数据库是保持数据库健康的重要步骤。通过遵循这些技巧和最佳实践,您可以最大程度地提升MySQL的效率,并提高应用程序的响应速度。

爱编程的鱼的博客 1970

mysql千万级数据量查询优化参考 —— 筑梦之路

Mysql查询性能优化要从三个方面考虑,库表结构优化、索引优化和查询优化。

筑梦之路 3765

MySQL——如何让你的查询更加高效?全方面优化查询数据

查询性能优化 优化数据访问 查询不需要的记录 MySQL是先返回全部结果集再进行计算 多表关联时返回全部列 总是取出全部列 去除全部列会让优化器无法完成索引覆盖扫描这类优化 重复查询相同的数据 比较好的方案是:初次查询时将这个数据缓存起来,需要的时候从缓存中取出 衡量查询开销的三个指标: 响应时间 扫描的行数 返回的行数 响应时间 看到时先想想这是否一个合理的值 这个查询需要哪些索引,执行计划是什么,需要多少个顺序和随机IO 扫描的行数和返回

lianghongliang66的博客 1872

高性能MYSQL(查询优化)

查询的生命周期:客户端到服务端,然后服务器上进行解析,生成执行计划,执行,返回结果给客户端。慢查询基础:优化数据访问 1.是否想数据库请求了不需要的数据,尽量查询需要的数据,不要返回不需要的数据。 避免:查询胥的记录;多表关联时返回全部的列;总是取出全部列;重复查询相同的数据 2. Mysql是否在扫描额外的记录 衡量查询开销的指标: 1)响应时间:服务时间和排队时间。服务时间是指数据库处

随风的博客 9814

如何设计高效合理的MySQl查询语句?23种常用类型汇总

MySQL对于很多Linux从业者而言,是一个非常棘手的问题,多数情况都是因为对数据库出现问题的情况和处理思路不清晰。在进行MySQL的优化之前必须要了解的就是MySQL的查询过程,很多的查询优化工作实际上就是遵循一些原...

cky8792的博客 230

在一个千万级的数据库查寻中,如何提高查询效率?

一、数据库设计方面 1、对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引; 2、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: sel...

徐刘根的博客 6万+
上一篇: MySQL 单表可以放多少数据,最多 2000 万?
下一篇: 可解决95%以上问题的Linux命令!能用到退休
Java_2017_csdn
博客等级 码龄10年 329粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值