数据库索引是一种用于加快数据库查询速度的数据结构,它类似于书籍的目录,可以帮助快速定位到表中某个或某些特定的行。数据库索引通常由一组索引键(或索引字段)构成,这些键的值被存储在一个数据结构中,以便快速查找特定的行。
数据库索引有多种分类方法,从索引的实现方式常见的有:
每种索引类型适用于不同的数据类型和查询类型,应根据具体需求选择合适的索引类型。
B+树是一种平衡树,每个节点包含一定数量的关键字和指向子节点的指针,以支持快速的查询和排序。B+树索引适用于各种数据类型,并且支持范围查询和排序,因此在许多数据库系统中广泛使用。
注: 图片来源自Wikipedia(https://zh.wikipedia.org/wiki/File:Bplustree.png)
当数据库执行查询时,它首先在B-树索引中搜索包含查询所需关键字的节点,然后通过指针找到包含该关键字的数据记录。如果查询是范围查询,则B-树索引还可以通过查询包含范围内关键字的节点,并返回所有符合条件的数据记录。
Hash索引是一种基于哈希表的索引,它使用哈希函数将数据映射到哈希表中的桶(bucket)。
注: 图片来源自Wikipedia(https://en.wikipedia.org/wiki/Hash_table)
当数据库执行查询时,它使用哈希函数计算查询所需关键字的哈希值,然后在哈希表中查找具有相同哈希值的数据记录。如果发现多个数据记录具有相同的哈希值,则必须使用比较运算符来确定实际的数据记录。
空间索引是一种专门用于处理空间数据的索引,通常用于地理信息系统(GIS)和空间数据库中。它是用于快速查询空间数据的位置和几何关系的索引。
注: 图片来源自Wikipedia
空间索引通常使用网格结构,如格网、网格图或四叉树,将空间数据划分为许多小的网格单元。每个网格单元存储其中的一个或多个数据点,并使用空间算法快速查询其他网格单元,以确定数据点的几何关系。
全文索引是用于快速搜索文本内容的索引。它可以在数据库中搜索文本字段,或者在文档管理系统中搜索文件内容。全文索引通常通过对文本内容进行分词(将文本分解为单词),并使用数据结构(如倒排索引)存储分词后的信息,以便快速查询搜索词。
Bitmap索引是一种特殊的数据索引,它通过将数据存储为二进制位映射(Bitmap)来加速查询。每个位代表一个数据记录是否符合某个特定条件。例如,如果某个位为1,则表示该记录符合某个条件,如果为0,则表示该记录不符合条件。
因此,Bitmap索引通常适用于具有较少不同值的列,以加速查询。
从唯一性的角度,索引可以分为唯一性索引和非唯一性索引。唯一性索引可以用来保证表中某个列的唯一性约束条件,通常用于实现主键约束和唯一性约束,数据库通常会为主键或是唯一性约束自动创建唯一性索引。
唯一性索引不仅可以提高查询的效率,还可以起到数据校验的作用,避免了重复数据的产生,提高数据的质量和准确性。它的缺点是每当有数据修改或是插入时,需要检查是否违反唯一性约束。
从聚簇率的角度,索引可以分为聚簇索引或非聚簇索引。聚簇索引的索引键的排列顺序和数据表中数据的排列顺序一致的索引,每个表只能有一个聚簇索引,因为数据表的数据只能以一种方式进行排序。
在一些比较先进的数据库优中,对于非聚簇索引也会计算其聚簇率,以方便优化器评估回表时磁盘IO的代价。聚簇率小的索引回表时,会引起磁盘IO的抖动,从而明显影响查询性能,一般来讲,聚簇率越大,其磁盘IO的代价越小。
聚簇索引有两种实现方式,
聚簇索引的优势是可以减少磁盘I/O次数,从而提高查询性能。但是,聚簇索引也有一些缺点,譬如当插入新数据时,它可能需要移动数据页或重新组织索引,这可能会对性能产生负面影响。
从是否是主键的角度,索引可以分为主键索引和二级索引,主键索引只能有一个,二级索引可以有多个。
从包含的索引列的数目的角度,索引可以分为单列索引和组合索引。组合索引可以满足多种查询条件,从而节省索引的空间和索引维护的代价。组合索引的匹配原则遵循最左前缀匹配原则,详细信息请参考《如何创建高效的索引》。
函数索引(或表达式索引)即基于函数或表达式的索引,它使用函数或是表达式提供计算好的值作为索引列构建索引,可以在不修改应用程序的情况下提高查询性能。案例如下:
alter table lineitem add index idx(DAYOFMONTH(l_shipdate));
DAYOFMONTH是PostgreSQL自带的函数,它从日期中获取天。
部分索引(Partial index)是建立在一个表的子集上的索引,而该子集是由一个条件表达式定义的,该索引只包含表中那些满足这个条件表达式的行。案例如下:
create index l_partkey_idx on lineitem(l_partkey) where l_shipdate > '2022-01-01';