liuyiy 2019-02-19
索引虐我千百遍,我待索引如初恋
当有人问到索引是什么时,大家都喜欢用“书的目录”来做类比,没有索引的数据库,就像是没有目录的书,想找第3章的第7小节,就要一页一页翻过去,最可怕的是翻到了还要把这本书翻完才算完;那反之有索引的数据库,就是有目录的书了,直接按目录找到就可以了。
书放个目录,人来翻找,那数据库是怎么“翻找”呢?“目录”又是怎么放的?
数据库在安装完成之后,安装程序会自动创建master、model、tempdb等几个特殊的”系统数据库“,其中master是数据库的主数据库,用于保存和管理其它系统数据库、用户数据库以及数据库的系统信息。
master中有一个名为sysindexes的系统表,专门管理索引。数据库查询数据表的操作都必须用到它,毫无疑义,它是本文主角之一。
PS:查看一张表的索引属性,可以在查询分析器中使用以下命令:select * from sysindexes where id=object_id('tablename') 。参数tablename为被索引的表名。
所以,我们现在有了一个认知:索引是专门放在一张表里的,且放的位置和其他数据表不一样。
先来介绍两个概念:聚集索引、非聚集索引
根据两者的特性,也很容易总结出他们的优缺点,即聚集索引查找速度更快,缺点则是对表进行修改速度较慢,因为要保持数据顺序一致,非聚集索引则反之。他们的适用场景如下:
接下来介绍一下平衡树
再回归到“目录”,在我们知道知道第3章第7节在236页时,你可能会随便翻,但更科学的方法的:先翻到书大概二分之一的地方,再在二分之一的书里找下一个二分之一,以此类推,直到找到正确的页数,熟悉算法的同学会发现,这是常见的”二分法“,微软在官方教程MOC里另有一种说法:叫B树(Balance Tree),即平衡树。
索引的实现就使用了B+树的数据结构,B+树内把真实的数据又放在了叶子节点中,非叶子节点中只存放了索引的数据,保证了数据项尽可能的多。
(B和B+树的区别在于,B+树的非叶子结点只包含导航信息,不包含实际的值,所有的叶子结点和相连的节点使用链表相连,便于区间查找和遍历。)
在对这两个概念有认知的基础下,我们来聊聊 数据库是怎么“翻找”的。
通过一个非聚集索引的访问案例来阐述。
假定在 name 这一参数上建立了非聚集索引,则执行如下语句时,查询过程是:
Select * From Member Where name='张三'
索引有一些先天不足:
当然建立索引的优点也是显而易见的:在海量数据的情况下,如果合理的建立了索引,则会大大加强数据库执行查询、对结果进行排序、分组的操作效率。
实践表明,不恰当的索引不但于事无补,反而会降低系统性能。因为大量的索引在进行插入、修改和删除操作时比没有索引花费更多的系统时间。比如在如下字段建立索引应该是不恰当的:1、很少或从不引用的字段;2、逻辑型的字段,如男或女(是或否)等。
综上所述,提高查询效率是以消耗一定的系统资源为代价的,索引不能盲目的建立,必须要有统筹的规划,一定要在“加快查询速度”与“降低修改速度”之间做好平衡,有得必有失,此消则彼长。这是考验一个DBA是否优秀的很重要的指标。