为什么需要索引?

数据库中的索引,就好比一本书的目录,可以快速进行特定值的定位与查找,从而加快数据查询的效率。

索引是帮助数据库管理系统高效获取数据的数据结构。

 

索引有哪些需求?

功能性需求:

  • 格式化数据 or 非格式化数据

    要构建索引的原始数据,可以分为两类,一类是结构化数据,比如MySQL 中的数据;另一类是非结构化数据,比如搜索引擎中网页。对于非结构化数据,一般需要做预处理,提取出查询关键词,对关键词构建索引。

  • 静态数据 or 动态数据

    如果原始数据是一组静态数据,在构建索引的时候,只需要考虑查询效率就可以了。不过大部分情况下,都是对动态数据构建索引,不仅要考虑到索引的查询效率,在原始数据更新的同时,还需要动态地更新索引。

  • 内存 or 磁盘

    如果索引存储在内存中,那查询的速度肯定要比存储在磁盘中的高。但在原始数据量很大的情况下,对应的索引可能也会很大,只能将索引存储在磁盘中了。

    实际上,还有第三种情况,那就是一部分存储在内存,一部分存储在磁盘,这样就可以兼顾内存消耗和查询效率。

  • 单值查找 or 区间查找

    散列表和平衡查找二叉树(红黑树)不能支持按照区间快速查找数据

    跳表支持按照区间快速查找数据

  • 单关键词查找 or 多关键字组合查找

    像 MySQL 这种结构化数据的查询需求,可以实现针对多个关键词的组合,建立索引;对于像搜索引擎这样的非结构数据的查询需求,可以针对单个关键词构建索引,然后通过集合操作,比如求并集、求交集等,计算出多个关键词组合的查询结果。

非功能性需求:

  • 存储空间

    如果存储在内存中,索引对占用存储空间的限制就会非常苛刻。

    如果存储在硬盘中,那索引对占用存储空间的限制,稍微会放宽一些。但也不能掉以轻心,有时候索引对存储空间的消耗会超过原始数据。

  • 维护成本

    基于动态数据集合构建的索引,在原始数据动态增删改的同时,还需要动态地更新索引。而索引的更新势必会影响到增删改操作的性能。

 

构建索引常用的数据结构有哪些?

内存索引,操作数据的时间复杂度低:

  • 有序数组

    如果数据是静态的(不会有插入、删除、更新操作),可以把数据的关键词(可供查询使用)抽取出来,组织成有序数组,然后利用二分查找算法来快速查找数据。

  • 跳表

    跳表通过灵活调整索引结点个数和数据个数之间的比例,可以很好地平衡索引对内存的消耗及其查询效率。

    Redis 中的有序集合,就是用跳表来构建的。

  • 散列表

    Redis 和 Memcache中,就是使用散列表来构建索引的。

  • 红黑树

    Ext 文件系统中,对磁盘块的索引,用的就是红黑树。

    Ext文件系统是Linux主流的文件系统。

磁盘索引,尽量减少磁盘的I/O操作:

  • B+树

    大部分关系型数据库的索引,比如 MySQL、Oracle,都是用 B+ 树来实现的。

  • LSM树

    写多读少的非关系型数据库,比如Hbase、RocksDB。

辅助索引:

  • 位图

  • 布隆过滤器

    可以针对数据,构建一个布隆过滤器,并且存储在内存中。当要查询数据的时候,我们可以先通过布隆过滤器,判定是否存在。如果通过布隆过滤器判定数据不存在,那我们就没有必要读取磁盘中的索引了。对于数据不存在的情况,数据查询就更加快速了。

 

什么情况下不适合创建索引?

索引的价值是帮我们从海量数据中找到想要的数据,如果数据量少,那么是否使用索引对结果的影响并不大。

  • 在数据表中的数据行数比较少的情况下,比如不到 1000 行,是不需要创建索引的。

  • 当数据重复度大,比如高于 10% 的时候,也不需要对这个字段使用索引(例如性别)。

 

索引有哪些种类?

功能逻辑:

  • 普通索引

    基础的索引,没有任何约束,主要用于提高查询效率

  • 唯一索引

    普通索引的基础上增加了数据唯一性的约束,在一张数据表里可以有多个唯一索引

  • 主键索引

    在唯一索引的基础上增加了不为空的约束,在一张表里最多只有一个主键索引

物理实现方式:

  • 聚集索引

    聚集索引的叶子节点存储了数据记录,表中数据记录按索引的排序方式进行存储。每一个表只能有一个聚集索引,因为数据行本身只能按一个顺序存储。

    读多写少情况下查询效率高。

  • 非聚集索引

    非聚集索引的叶子节点存储了数据位置,不影响数据表的物理存储顺序。每一个表可以有多个非聚集索引,也就是多个索引目录提供数据检索。

    写多读少情况下插入删除效率高。

字段个数:

  • 单一索引

    索引列为一列时为单一索引

  • 联合索引

    多个列组合在一起创建的索引为联合索引,联合索引存在最左匹配原则,按照最左优先的方式进行索引的匹配。

参考:

https://time.geekbang.org/column/article/112023

https://time.geekbang.org/column/article/78449

 

posted on 2022-07-05 18:43  心海湖一霸  阅读(86)  评论(0)    收藏  举报