索引到底能提升多少查询效率?何时该使用索引?一文快速搞懂数据库索引及合理使用它

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 索引到底能提升多少查询效率?何时该使用索引?一文快速搞懂数据库索引及合理使用它

一、前言


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


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


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


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


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


现在有一个学生表student,有1000万条数据


90ac6a13282640a795329d2db831efad.png


未加索引,查询class_id=2的学生信息的耗时:SELECT * FROM student WHERE class_id=2 花费了3.357秒

fb357f269b3d43be88c329042f7d058b.png

加上索引,查询class_id=2的学生信息的耗时:SELECT * FROM student WHERE class_id=2 花费了0.017秒


0d1d7412e87441b69bf5e127d38c9e2a.png


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的前提条件是两个结果集没有重复数据。


八、总结


索引是非常重要的技术!


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


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


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

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
19天前
|
数据库 索引
深入探索数据库索引技术:回表与索引下推解析
【10月更文挑战第15天】在数据库查询优化的领域中,回表和索引下推是两个核心概念,它们对于提高查询性能至关重要。本文将详细解释这两个术语,并探讨它们在数据库操作中的作用和影响。
42 3
|
19天前
|
数据库 索引
深入理解数据库索引技术:回表与索引下推详解
【10月更文挑战第23天】 在数据库查询性能优化中,索引的使用是提升查询效率的关键。然而,并非所有的索引都能直接加速查询。本文将深入探讨两个重要的数据库索引技术:回表和索引下推,解释它们的概念、工作原理以及对性能的影响。
36 3
|
17天前
|
SQL 安全 Java
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
13 1
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
|
5天前
|
数据库 索引
数据库索引
数据库索引 1、索引:建立在表一列或多列的辅助对象,目的是加快访问表的数据。 2、索引的优点: (1)、创建唯一性索引,可以确保数据的唯一性; (2)、大大加快数据检索速度; (3)、加速表与表之间的连接; (4)、在查询过程中,使用优化隐藏器,提高系统性能。 3、索引的缺点: (1)、创建和维护索引需要耗费时间,随数据量增加而增加; (2)、索引占用物理空间; (3)、对表的数据进行增删改时,索引需要动态维护,降低了数据的维护速度。
15 2
|
1月前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
61 3
Mysql(4)—数据库索引
|
14天前
|
存储 缓存 固态存储
怎么让数据库查询更快
【10月更文挑战第28天】
24 2
|
15天前
|
存储 缓存 关系型数据库
怎么让数据库查询更快
【10月更文挑战第25天】通过以上综合的方法,可以有效地提高数据库查询的速度,提升应用程序的性能和响应速度。但在优化过程中,需要根据具体的数据库系统、应用场景和数据特点进行合理的调整和测试,以找到最适合的优化方案。
|
15天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
77 1
|
17天前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
191 2
|
17天前
|
SQL 关系型数据库 数据库
PostgreSQL性能飙升的秘密:这几个调优技巧让你的数据库查询速度翻倍!
【10月更文挑战第25天】本文介绍了几种有效提升 PostgreSQL 数据库查询效率的方法,包括索引优化、查询优化、配置优化和硬件优化。通过合理设计索引、编写高效 SQL 查询、调整配置参数和选择合适硬件,可以显著提高数据库性能。
108 1