索引到底能提升多少查询效率?何时该使用索引?一文快速搞懂数据库索引及合理使用它_索引越多查询效率越高吗-程序员宅基地

技术标签: mysql  数据库  索引  sql  

一、前言

无论是面试、还是日常工作中,或多或少都会使用或者听到别人谈论索引这个技术。

然而很大一部份程序员对索引的了解仅限于到“加索引能使查询变快”这个概念为止。

使用索引也很简单,然而, 会使用索引是一回事, 而深入理解索引原理又能恰到好处使用索引又是另一回事。

这已经是两个相差甚远的技术层级了。

二、千万级数据表索引和无索引查询效率对比

现在有一个学生表student,有1000万条数据
在这里插入图片描述
未加索引,查询class_id=2的学生信息的耗时SELECT * FROM student WHERE class_id=2 花费了3.357秒
在这里插入图片描述
加上索引,查询class_id=2的学生信息的耗时SELECT * FROM student WHERE class_id=2 花费了0.017秒
在这里插入图片描述
1000万条数据下,两个查询的性能差了近200倍!!

这个差距是特别大的! 难怪需要加索引!!!

三、什么是索引

网上很多讲解索引的文章对索引的描述是这样的:

索引就像书的目录, 通过书的目录就可以准确的定位到书籍的具体的内容。

这句话概述的非常正确!

但说了跟没说一样,懂的人自然懂!不懂的人感觉懂了,但还是一脸蒙的状态!

其实想要理解索引原理,必须清楚一种数据结构:

平衡树」(非二叉),也就是b tree或者 b+ tree

当然, 有的数据库也使用哈希桶作用索引的数据结构 , 然而, 主流的RDBMS都是把平衡树当做数据表默认的索引数据结构的。

我们平时建表的时候都会为表加上主键, 在某些关系数据库中, 如果建表时不指定主键,数据库会拒绝建表的语句执行。

事实上, 一个加了主键的表,并不能被称之为“表”。一个没加主键的表,它的数据无序的放置在磁盘存储器上,一行一行的排列的很整齐。
如果给表上了主键,那么表在磁盘上的存储结构就由整齐排列的结构转变成了树状结构,也就是上面说的“平衡树”结构,换句话说,就是整个表就变成了一个索引。

没错, 再说一遍, 整个表变成了一个索引!

也就是所谓的“聚集索引”。 这就是为什么一个表只能有一个主键, 一个表只能有一个“聚集索引”,因为主键的作用就是把“表”的数据格式转换成“树(索引)”的格式。

未加索引时,之前执行的查询sql会让数据库系统逐行的遍历整张表,对于每一行都要检查其class_id字段是否等于“2”。因为我们要查找所有class_id为“2”的员工,所以当我们发现了一条class_id是“2”的记录后,并不能停止继续查找,因为可能还有class_id等于“2”的其他记录。

这就意味着,对于表中的千万条记录,数据库每一条都要检查。这就是所谓的“全表扫描”( full table scan)

而加上索引的最大作用就是加快查询速度,它能从根本上减少需要扫表的记录/行的数量。

四、Mysql中的索引

在MySQL中, 索引有两种分类方式:逻辑分类和物理分类。

按照逻辑分类,索引可分为:

主键索引:一张表只能有一个主键索引,不允许重复、不允许为 NULL;

唯一索引:数据列不允许重复,允许为 NULL 值,一张表可有多个唯一索引,但是一个唯一索引只能包含一列,比如身份证号码、卡号等都可以作为唯一索引;

普通索引:一张表可以创建多个普通索引,一个普通索引可以包含多个字段,允许数据重复,允许 NULL 值插入;

全文索引:让搜索关键词更高效的一种索引。

按照物理分类,索引可分为:

聚集索引:一般是表中的主键索引,如果表中没有显示指定主键,则会选择表中的第一个不允许为 NULL 的唯一索引,如果还是没有的话,就采用 Innodb 存储引擎为每行数据内置的 6 字节 ROWID 作为聚集索引。每张表只有一个聚集索引,因为聚集索引的键值的逻辑顺序决定了表中相应行的物理顺序。聚集索引在精确查找和范围查找方面有良好的性能表现(相比于普通索引和全表扫描),聚集索引就显得弥足珍贵,聚集索引选择还是要慎重的(一般不会让没有语义的自增 id 充当聚集索引);

非聚集索引:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同(非主键的那一列),一个表中可以拥有多个非聚集索引。

在目前用的最多的mysql的InnoDB存储引擎中,是使用B+Tree索引方法来进行索引建立的。

B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引。

B+树中的B代表平衡(balance),而不是二叉(binary),因为B+树是从最早的平衡二叉树演化而来的。先了解二叉查找树、平衡二叉树(AVLTree)和平衡多路查找树(B-Tree),B+树即由这些树逐步优化而来。
具体的讲解可参考:https://www.cnblogs.com/wuzhenzhao/p/10341114.html 该博客。

五、索引的优缺点

优点:

1、索引能够提高数据检索的效率,降低数据库的IO成本。

2、通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性,创建唯一索引

3、在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间

4、加速两个表之间的连接,一般是在外键上创建索引

缺点:

1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加

2.索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大

3.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度

六、索引何时应该使用

需创建索引的情况

1.主键,自动建立唯一索引
2.频繁作为查询的条件的字段
3.查询中与其他表关联的字段存在外键关系
4.查询中排序的字段,排序字段若通过索引去访问将大大提高排序的速度
5.查询中统计或者分组字段

避免创建索引的情况

1.数据唯一性差的字段不要使用索引
比如性别,只有两种可能数据。意味着索引的二叉树级别少,多是平级。这样的二叉树查找无异于全表扫描。

2.频繁更新的字段不要使用索引
比如登录次数,频繁变化导致索引也频繁变化,增大数据库工作量,降低效率。

3.字段不在where语句出现时不要添加索引
只有在where语句出现,mysql才会去使用索引

4.数据量少的表不要使用索引
使用了改善也不大

七、哪些sql能命中索引

1.前导模糊查询不能使用索引,  如name like ‘%涛’

2、Union、in、or可以命中索引,建议使用in。

3、负条件查询不能使用索引,可以优化为in查询,其中负条件有!=、<>、not in、not exists、not like等

4、联合索引最左前缀原则,又叫最左侧查询,如果在(a,b,c)三个字段上建立联合索引,那么它能够加快a|(a,b)|(a,b,c)三组的查询速度。

5、建立联合查询时,区分度最高的字段在最左边

6、如果建立了(a,b)联合索引,就不必再单独建立a索引。同理,如果建立了(a,b,c)索引就不必再建立a,(a,b)索引

7、存在非等号和等号混合判断条件时,在建索引时,要把等号条件的列前置

8、范围列可以用到索引,但是范围列后面的列无法用到索引。

索引最多用于一个范围列,如果查询条件中有两个范围列则无法全用到索引。范围条件有:<、<=、>、>=、between等。

9、把计算放到业务层而不是数据库层。在字段上计算不能命中索引,

10、强制类型转换会全表扫描,

如果phone字段是varcher类型,则下面的SQL不能命中索引。Select * fromuser where phone=13800001234

11、更新十分频繁、数据区分度不高的字段上不宜建立索引。

更新会变更B+树,更新频繁的字段建立索引会大大降低数据库性能。

“性别”这种区分度不太大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类似。

一般区分度在80%以上就可以建立索引。区分度可以使用count(distinct(列名))/count(*)来计算。

12、利用覆盖索引来进行查询操作,避免回表。

被查询的列,数据能从索引中取得,而不是通过定位符row-locator再到row上获取,即“被查询列要被所建的索引覆盖”,这能够加速度查询。

13、建立索引的列不能为null,使用not null约束及默认值

14、利用延迟关联或者子查询优化超多分页场景,

MySQL并不是跳过offset行,而是取offset+N行,然后放弃前offset行,返回N行,那当offset特别大的时候,效率非常低下,要么控制返回的总数,要么对超过特定阈值的页进行SQL改写。

15、业务上唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。

16、超过三个表最好不要用join,需要join的字段,数据类型必须一致,多表关联查询时,保证被关联的字段需要有索引。

17、如果明确知道查询结果只要一条,limit 1能够提高效率,比如验证登录的时候。

18、Select语句务必指明字段名称

19、如果排序字段没有用到索引,就尽量少排序

20、尽量用union all 代替 union。Union需要将集合合并后在进行唯一性过滤操作,这会涉及到排序,大量的cpu运算,加大资源消耗及延迟,当然,使用union all的前提条件是两个结果集没有重复数据。

八、总结

索引是非常重要的技术!

但每建立一个索引,实际上都需要在硬盘上开辟一块空间用于存储这个索引所需要的数据结构(虽然表述不太准确但是是这个意思),因此不建议对太长的字段建立索引。

而且建立的索引并不是越多越好,因为索引虽然能够提高查询效率,但是会大大得影响插入、删除和修改的效率,因为每一次数据的更新都会牵涉到对索引的修改。

综上所述,往往在对于大量数据的插入的情况的时候,我们需要先删除掉数据表的索引,等插入完毕后重新建立索引,这样才能最大限度地保证数据库的效率!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/momoda118/article/details/119535217

智能推荐

wifi相关工具移植_编译wifi工具-程序员宅基地

文章浏览阅读321次。Linux:交叉编译WiFi工具iwconfig(wireless tools)、iw、wpa_supplicant、DHCP、hostapd(文末附使用方法)_编译wifi工具

itext使用模板生成pdf文件_itext 通过 pdf 模板生成 pdf,动态列表-程序员宅基地

文章浏览阅读1.1w次。用pdf模板生成pdf文档很简单,首先需要手动做个pdf模板,上面有很多的类似html里的text域的东西,给他们起好名字,在程序里填充就可以了。虽然由于不会做模板(实际上由于短时间无法去熟悉使用Adobe Acrobat )而没有用到此篇文章(转载的别人的)(只好手动生成),但是感觉写的还是不错的。贴出来,以便将来用到了查看。首先要定义一个DataBean接口,代码如下:pu_itext 通过 pdf 模板生成 pdf,动态列表

论文工具——ChatGPT结合PlotNeuralNet快速出神经网络深度学习模型图_gpt4 使用plotneuralnet编码生成图片-程序员宅基地

文章浏览阅读1.9k次。* PlotNeuralNet是一个带有python借口的latex包,能够生成任何你需要的神经网络的可视化图片。生成的图片质量很高,可以用于课程汇报,或者学术论文。* 你可以直接使用latex编译程序,编写相关的代码,自动会生成对应的图片。我一般是使用overleaf写的latex代码,线上可以直接渲染,并下载对应的pdf文件_gpt4 使用plotneuralnet编码生成图片

_stdcall与_cdecl的区别(函数调用方式)__stdcall 和 __cdecl 的区别浅析-程序员宅基地

文章浏览阅读278次。1. _cdecl(1).是C Declaration的缩写,表示C语言默认的函数调用方法,实际上也是C++的默认的函数调用方法。(2).所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。具体所示:调用方的函数调用->被调用函数的执行->被调用函数的结果返回->调用方清除调整堆栈。(3).被调用函数无需要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完__stdcall 和 __cdecl 的区别浅析

大数据可视化网页设计源码分享_可视化编辑网站源码-程序员宅基地

文章浏览阅读557次,点赞2次,收藏2次。大数据网页设计_可视化编辑网站源码

头歌c语言实训项目-循环结构程序设计_c语言水仙花数头歌-程序员宅基地

文章浏览阅读2.4k次,点赞3次,收藏16次。c语言经典例题-循环结构程序设计_c语言水仙花数头歌

随便推点

高精度色选机系统的项目实现_色选机软件系统-程序员宅基地

文章浏览阅读279次。随着我国色选机产业的不断发展,以及粮食、矿产、再生资源等行业的机器智能化程度的提高,国内主要的色选机研制企业都在谋求生产规模的扩大,与此同时,国外著名色选企业也在大举进入国内市场。本项目旨在通过技术创新和实际应用,研发一款高精度色选机,为目标行业提供先进的色选解决方案,在农产品种类繁多、品质要求严格的生产环境中,高效、准确地实现对农产品的色彩分选,提高生产效率,减少人工成本,降低人为误差,从而提升农产品的质量和附加值,在目标行业中取得显著的经济和社会效益,推动行业的数字化转型和智能化升级。_色选机软件系统

Android 开发三年,跳槽大厂无望,意外获得《Android面试宝典》助我跳槽字节、薪资翻倍-程序员宅基地

文章浏览阅读778次,点赞21次,收藏20次。每一个移动开发者都在为 Flutter 带来的“快速开发、富有表现力和灵活的 UI、原生性能”的特色和理念而痴狂,从超级 App 到独立应用,从纯 Flutter 到混合栈,开发者们在不同的场景下乐此不疲的探索和应用着 Flutter 技术,也在面临着各种各样不同的挑战。通过此工具开发的程序直接在本地运行,而不是虚拟机。,尤其是非计算机专业的同学,面试官一上来肯定是问你基础,要是基础表现不好很容易被扣上基础不扎实的帽子,常见的就那些,只要你平时认真思考过基本上面试是没太大问题的。

计算机专业与职业之间的关系,CS,EE和IS 之间的情感纠葛~~-程序员宅基地

文章浏览阅读1.1k次。原标题:CS,EE和IS 之间的情感纠葛~~俗话讲的好,学个码,编个程,条条道路皆光明。在过去10年间,计算机科学(Computer Science, 缩写CS)已成为家喻户晓的明星学科之一,很多出国留学的申请者都将CS作为自己未来的学习和职业目标,但随着专业热门程度的不断攀升,CS的申请难度不可避免的也急剧增加,往往申请了一大批CS项目却难以最终获得心仪学校的青睐。而为了平衡自己的申请难度,很多..._计算机专业与职业之间的关系

Android的系统架构_2.1 android系统架构 4 2.2 android组件 4 2.3相关技术 6-程序员宅基地

文章浏览阅读475次。如果说一个成功男人的背后会有一个默默支持的女人的话,那么一个优越稳定的平台背后必有一个成熟的系统架构所支撑着。那么,Android的系统架构是怎么样的呢?从下图我们可以从整体上有个大致的了解(图片来源互联网): 从上图中可以看出,Android系统架构为四层结构,从上层到下层分别是应用程序层、应用程序框架层、系统运行库层以及Linu_2.1 android系统架构 4 2.2 android组件 4 2.3相关技术 6

Delphi接口Post内Authorization传Bearer Token问题_delphi tnethttpclient authorization post-程序员宅基地

文章浏览阅读968次,点赞22次,收藏20次。Post内Authorization传Bearer Token_delphi tnethttpclient authorization post

如何使用 Elasticsearch 作为向量数据库_elasticsearch 向量化数据库-程序员宅基地

文章浏览阅读1.8k次,点赞34次,收藏20次。在今天的文章中,我们将很快地通过 Docker 来快速地设置 Elasticsearch 及 Kibana,并设置 Elasticsearch 为向量搜索。_elasticsearch 向量化数据库