关于数据库索引

概述

索引是与表或视图关联的磁盘上结构,可以加快从表或视图中检索行的速度。索引包含由表或视图中的一列或多列生成的键。这些键存储在一个B-树中,使数据库可以快速有效地查找与键值关联的行。
对表列定义了PRIMARY KEY约束时,会自动创建唯一索引(默认是聚集索引,可以指定为非聚集索引)。

优点

如要在大量数据中进行查找,数据库必须查找所有的数据表。如果有了可用的索引,数据库只要在索引层浏览每个索引分页的数据,再找到所需要的少量数据分页即可,带来的性能提升非常大。若考虑到内存的使用、时间所造成的锁定扩大等综合效应,索引使用的优劣会让系统性能天差地别。

缺点

过多的索引会对新增、修改和删除数据不利。数据库除了更新数据库表之外,还要维护各个索引的结构。

聚集索引(CLUSTERED)

聚集索引会根据建索引的字段的值排序和存储数据行。

特点

每个表只能有一个聚集索引。

  • 适用情形
    • 值唯一或大部分值不相同。
    • 需要按顺序访问。
    • 经常需要对表中检索到的数据进行排序。
    • 作为查询条件时有很多条记录都符合该条件(来自《SQL Sever性能调校》P275)。
  • 不适用情形
    • 列频繁更改,这将导致数据库引擎必须整行移动数据。
    • 宽键——若干列或若干大型列的组合。

非聚集索引(NONCLUSTERED)

非聚集索引包含索引键值和指向表数据存储位置的行定位器。索引结构独立于数据行。

  • 适用情形
    • 使用JOIN或GROUP BY子句。
    • 不返回大型结果集。
    • 经常被作为查询的条件的列。
  • 不适用情形
    • 作为查询条件时选择性不高,即有很多记录符合该条件(这样的情形如果使用非聚集索引的效率甚至不如数据表扫描)。

索引结构从上到下包括非子叶层、子叶层(存放键值和数据行的指针)和堆(无序的数据行)。
当从非聚集索引从结构中找到符合的记录时,虽然在子叶层键值是有序的,因此可能符合条件的键值都在一个分页上,但是在堆中存放的数据行是无序的,所以符合记录的数据时分散在文档的各个地方。而SQL Server每次读取数据都是以分页为单位,因此当符合查询条件的记录很多时,通过非聚集索引访问将导致分页读取非常频繁,就算两条数据在同一个分页,还是要重复读这个分页两次。

是否要建立索引

索引太多会降低数据的增删改操作的效率,而索引太少会导致查找效率低下。索引的取舍就要依靠经验了。有以下几点可以参考。

选择性(Selectivity)

选择性 = 符合条件的记录数目 / 总记录数

这个值越小,越适合采用(非聚集)索引。

数据密度(Density)

数据密度 = 1 / 键值唯一的记录数

当数据密度越小,即唯一性越高时,越适合建立索引。

数据分布(Distribution)

代表数据记录分布的状态,是平均分布,还是聚集在部分区域。可以让我们更好地判断条件的选择性是否很高。

给鸡排饭加个蛋