索引是重要的提升磁盘数据检索速度的方式。只要涉及数据检索就必然需要使用索引来提高效率。因此索引不仅在关系型数据库中广泛应用,在NoSQL等其它类型的数据库中也同样流行。
索引是建立在key上的。key有一些基本的类型和概念,请先参考下面的链接做初步的了解。
http://blog.csdn.net/onlyqi/article/details/51096412
另外由于B-tree结构的索引对磁盘数据的检索有极大的效率提高,因此所有的数据库管理系统,包括所有的关系型数据库,NoSQL数据库等等,只要数据是存储在磁盘上,默认都使用B-tree索引来提高效率。一些在内存中的数据可能会使用其它类型的索引,例如MySQL中使用memory引擎时(即表数据存在于内存中)时,默认索引的类型是hash索引。
关于B-tree结构的索引如何工作,可参看另外一篇文章:
http://blog.csdn.net/onlyqi/article/details/50436531
本文介绍一些常见的高级索引功能,即特色的索引功能。
Clustered-index and Non-indexed-index
SQL Server有聚集索引和非聚集索引的概念,主要区别是创建聚集索引会导致SQL Server按照聚集索引的顺序对表数据进行重排。Oracle则提供一种特殊的表称为index-organized table,和聚集索引类似。
但总体来说,SQL Server强调对聚集索引的使用,因为一旦表数据是有序的,就可以使用B-tree快速定位数据。而Oracle更强调对主键的使用,由于主键的唯一性,也使得Oracle可快速定位数据(在有序的主键索引中定位数据后,使用ROWID快速定位到数据的物理位置)。
非关系型数据库的索引则一般没有此类区别。
Function index/create index on computed columns
指基于计算过的字段值建立索引。例如表中有一个字段Gender,值为0或1,分别代表男性和女性。现在建立一个函数或表达式,将0和1转换为“male”和“female”,并按照转换后的字符来建立索引。该功能支持逻辑复杂的function或表达式,对于那些使用了这些函数或表达式的SQL,可以提高效率。
在Oracle中称为function index,而在SQL Server中称为create index on computed columns,MySQL则不支持类似的索引。
Prefix Index
prefix指的是仅对索引字段的前N个字符创建索引。当字段本身比较长,但是字段的前n个字符选择性比较大的时候,使用前缀索引可以减小索引数据,提高查询效率。
Oracle和MySQL都提供前缀索引,SQL Server似乎没有。
Fulltext Index
Oracle,MySQL和SQL Server都提供全文索引。全文索引和普通索引的机制完全不同,类似一种内置的搜索引擎。全文索引通常用来搜索自然语言文本,例如报纸文章,网页内容等等.
主键Primary Key
所有的数据库系统都可使用主键,包括关系型数据库和非关系型数据库。从定义来看,主键最大的意义在于唯一性,也就是使用主键可以快速定位到查找的行或记录。对于关系型数据库,主键一般可以随意指定。NoSQL数据库一般限制大一些。例如MongoDB中,每行数据都有一个自动生成的字段_ID,主键也自动建在该字段上且不能改变。
Filtered index/partial index/conditional index
当一个字段的值只有一小部分和查询相关时,可以使用过滤索引来索引少量的数据集。例如,当一个字段的大部分值都为空,且SQL仅查询该字段非空的行,那么可以基于非空值建立过滤索引。因此该功能在当数据集很稀疏(sparse)时很有用。
例如:
CREATE NONCLUSTERED INDEX FIBillOfMaterialsWithEndDate
ON Production.BillOfMaterials (ComponentID, StartDate)
WHERE EndDate IS NOT NULL ;
GO
相对索引所有行,过滤索引使用空间更小,维护成本更低。但需要注意的是,过滤索引只能是非聚集索引。
Oracle和MySQL都没有提供该功能,但有一些workaround。SQL Server可参考:
https://technet.microsoft.com/en-us/library/jj835095(v=sql.110).aspx#Filtered
覆盖索引
覆盖索引并不是一类特殊索引,而是指基于查询涉及的全部字段建立一个联合索引。覆盖索引最大的意义在于,由于索引数据本身已经包含了查询需要的所有字段值,因此不再需要到数据页面取得别的字段值,从而提高了效率。例如:
SELECT C1,C2,C3
FROM Table
WHERE C4=10
若此时在C4,C1,C2,C3上建立联合索引,该SQL运行时就可以基于C4做条件过滤,同时从索引数据就得到了C1,C2,C3的值。如果此时select中还有一个字段C5,则查询引擎必须根据指针到对应的数据页面上,查询C5的值。