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

本文分享自华为云社区《索引到底能提升多少查询效率?何时该使用索引?一文快速搞懂数据库索引及合理使用它》,作者: 曲鸟。

一、前言

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

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

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

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

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

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

八、总结

索引是非常重要的技术!

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

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

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

点击关注,第一时间了解华为云新鲜技术~

你真的会使用数据库的索引吗?相关推荐

  1. 数据库建立索引、数据表创建规则、备用字段 / 保留字段 / 预留字段

    数据库建立索引 数据库.数据表建立索引的原则 数据库建立索引的原则 1,确定针对该表的操作是大量的查询操作还是大量的增删改操作. 2,尝试建立索引来帮助特定的查询.检查自己的sql语句,为那些频繁在w ...

  2. 数据库创建索引的原则

    数据库建立索引的原则 铁律一:天下没有免费的午餐,使用索引是需要付出代价的 索引的优点有目共睹,但是,却很少有人关心过采用索引所需要付出的成本.若数据库管理员能够对索引所需要付出的代价有一个充分的认识 ...

  3. PHP面试MySQL数据库的索引

    你好,是我琉忆,PHP程序员面试笔试系列图书的作者. 本周(2019.3.4至3.8)的一三五更新的文章如下: 周一:PHP面试MySQL数据库的基础知识 周三:PHP面试MySQL数据库的索引 周五 ...

  4. postgresql 查看数据库,表,索引,表空间以及大小

    为什么80%的码农都做不了架构师?>>>    postgresql 查看数据库,表,索引,表空间以及大小 1.查看数据库 #psql -U postgres //\加上字母l,相当 ...

  5. 4.1.2 OS之文件逻辑结构(顺序文件、索引文件、索引顺序文件、多级索引顺序文件)关于数据库的索引如聚簇索引可以看一下索引文件例题的解析,感觉还是可以收获到东西的

    文章目录 0.思维导图 1.无结构文件 2.有结构文件 有结构文件的逻辑结构 顺序文件 索引文件 索引顺序文件 多级索引顺序文件 0.思维导图 1.无结构文件 2.有结构文件 定长记录: 不定长记录: ...

  6. mysql数据库添加索引和去重

    1. 数据库添加索引 alter table dir_list add index dir_name(dir_name); alter table dir_list add index file_na ...

  7. 数据库-优化-索引-索引的优化

    索引的优化 1.什么是索引? 索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容. 数据库使用索引以找到特定值,然后顺指针找到包含该值的行.在表中建立索引,然后在索引中找到符合查询条件 ...

  8. 定时创建oracle索引,oracle数据库关于索引建立及使用的详细介绍

    索引的说明 索引是与表相关的一个可选结构,在逻辑上和物理上都独立于表的数据,索引能优化查询,不能优化DML操作,Oracle自动维护索引,频繁的DML操作反而会引起大量的索引维护. 如果SQL语句仅访 ...

  9. 数据库创建索引有什么优点和缺点

    数据库中索引的优缺点为什么要创建索引呢?这是因为,创建索引可以大大提高系统的性能,优点:第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性.第二,可以大大加快数据的检索速度,这也是创建索引 ...

最新文章

  1. 如何设计一个通用的权限管理系统
  2. boost::multiprecision模块logged_adaptor相关的测试程序
  3. MySQL的用户和授权
  4. C#实现写入文本文件内容功能
  5. 连通域标记——实现硬币自动计件
  6. wex5 app应用 定时退出
  7. 中秋快乐:数据库的全家福喜添新员
  8. 微信 iOS 版正式支持深色模式;谷歌宣布彻底取消I/O开发者大会;Visual Studio 2019 16.5发布|极客头条...
  9. [渝粤教育] 重庆工程职业技术学院 Linux服务器配置与管理 参考 资料
  10. 解决执行hive语句时出现虚拟内存不够的问题
  11. 数据分析A/BTest之APP页面
  12. hive sql系列(七)——查询前20%时间的订单信息
  13. 2021--ICPC网络预选第一场--A Busiest Computing Nodes
  14. MVC.Net: 解决Attempted to access an unloaded appdomain的问题
  15. realmeq参数配置详情_realmeq参数配置-realmeq手机性能规格详情
  16. 关于年份和月份的计算
  17. js  计算是今天多少周
  18. 码率控制(二):CRF详解
  19. 使用frp实现内网穿透(含SSH、远程桌面、文件访问等)
  20. 3、第三方软件中使用TWS API的相关问题

热门文章

  1. 编写代码的软件用什么编写的_如果您编写代码,这就是您的黄金时代
  2. jQuery源码分析 Sizzle选择器
  3. JavaScript 经典设计模式
  4. HTML map元素
  5. macbook配置java环境变量_如何安装Java和配置环境变量
  6. mysql表设计很多非常大的varchar_聊一聊数据库(MySQL)设计中的数据类型优化
  7. 计算机专业简历中技能特长怎么写,简历上特长技能应该怎么填写
  8. 网站整体流程_企业建设网站流程解析-上海回声网络
  9. python 的多线程执行速度
  10. struct和union,enum分析