在前面一篇文章中谈到适当地建立索引能够大幅度地提升SQL语句查询速度,然而并不是在什么情况下都适合建立索引,下面来谈一下什么情况下适合建立索引、建立什么样的索引以及建立索引带来的好处和坏处。
一.索引的概念
广义的索引是指:将具有检索意义的事项按照一定方式排列,以方便进行检索。数据库中的索引是指:将数据库表中的一列或者多列按照一定的方式进行组织以方便对数据库表中的内容进行查询。
字典是广义的索引最好的例子,比如我们在字典中查找"陈"字,有两种查找方式:拼音查找和偏旁查找。拼音查找的前提是知道这个字的大概读音是"chen",然后去目录的拼音页列表查找到拼音为"chen"的汉字所在的页码,比如找到拼音为"chen"的汉字所在的起始页码为100,然后就会直接把字典翻到100页,如果该汉字恰好在100页,则查找到该汉字了,如果不在100页,那么继续往后面翻几页就会找到该汉字了。进行偏旁查找不需要知道该汉字的读音,只需要先在目录的偏旁列表中找到" 阝"对应的页码比如说12,然后去12页找到"陈"字所在的具体页码比如说101,最后只需要直接把字典翻到101页就可以看到"陈"字了。试想一下如果字典没有这个目录,要想在字典中找到某个汉字的话是很难的,最直接的办法可能就是从字典的正文第一页逐页查找直到找到该汉字为止,这个过程所耗费的时间是可想而知的,可能找一上午都找不到要找的汉字。
数据库中的索引跟字典的目录类似。数据库文件中的内容是存储在磁盘上的,当在数据库中查找记录时,如果能获得该记录在磁盘上存储的位置,就能迅速找到该记录,就跟查找汉字一样,否则的话就只有对数据库表中的所有内容进行扫描,直到找到符合条件的记录为止,这样显然会消费很多的时间。因此适当地创建索引能够加快查询速度。比如,我有一张表
peple( id integer(PK), name varchar(40) , age tinyint , tel varchar(20) )
里面有若干条数据:
1 Tom 20 85443452 Mark 28 67893533 Jim 18 139456734564 Jack 20 86754565 Jemyy 12 6789456
然后执行语句 select * from people where name='Jemyy';
会对所有的数据记录进行扫描逐一进行条件匹配,直到找到符合条件的记录。如果在name列上建立了索引,与字典的目录进行类比,假如把name列按照字母升序进行排列,然后可能就得到一个目录:
Jack 第四条记录的存储位置 Jemyy 第五条记录的存储位置 Jim 第三条记录的存储位置 Mark 第二条记录的存储位置 Tom 第一条记录的存储位置
查找的时候先找到Jemyy得到该记录的存储位置,然后根据存储位置获取该记录的内容。上面过程只是类比字典的查找对索引的一个理解,实际当中SQL利用索引进行查找的过程可能跟上面略有不同(没有研究过实际的SQL利用索引进行查找的过程,这个估计得需要读SQL引擎的源码),但是原理是类似的。
二.索引的分类
根据索引项与表中记录的物理顺序是否一致索引可以分为聚簇索引和非聚簇索引。索引项的顺序与表中记录的物理顺序一致的索引称作为聚簇索引,不一致的索引则称为非聚簇索引。比如字典的拼音查找目录就是聚簇索引,而偏旁查找目录则是非聚簇索引。
根据索引包含的列的多少分为多列索引和单列索引,在创建索引的时候,可以选择在某一列上创建索引,也可以选择在多个列上创建索引。
还有一种叫做唯一索引,表示此索引的每一个索引项对应一个唯一的数据记录。
根据聚簇索引和非聚簇索引的概念可以知道,在一张表上只会有一个聚簇索引,因为一张表中的记录的物理顺序规则只有一种,而可以有多个非聚簇索引。
三.索引的创建
在创建索引之前,要考虑好是否适合在某些列上创建索引,创建聚簇索引还是非聚簇索引,是创建单列索引还是多列索引,亦或是唯一索引。
创建索引的SQL语句格式为:
create [unique][cluster|noncluster] index indexname on tablename([column asc|desc,column asc|desc..)
在创建索引时,unique和cluster|noncluster以及asc|desc是可选的,当没有指定索引为唯一索引时,默认为非唯一索引;没有指定索引为聚簇索引还是非聚簇索引时,则默认为非聚簇索引;没有指定索引值的排序方式时,默认为asc升序。
一般情况下来说,在经常需要进行搜索、进行外连接以及排序的列上比较适合建立索引,而很少使用到或者需要经常被修改的列上则不适合建立索引。建立索引虽然能够加快查询速度,但是同时也为数据库的维护带来了不便。由于要对索引进行存储,所以建立索引带来了额外的空间消耗;并且建立索引对数据库的修改造成了很大的不便,当要往数据库里插入数据或者修改数据时,索引也会随之自动进行修改,这个时候会带来很大的时间消耗。因此如果在一开始没考虑好,比如在需要经常修改的列上建立索引,后期的维护是很麻烦的。
当需要返回某个范围内的值的时候,选择创建聚簇索引是比较合适的,就跟拼音查找类似,可以找到读音为"chen"的若干个汉字。
而对于多列索引和单列索引的选择则一般需要根据where子句的判断条件来选择。比如:
select * from peple where name='jack'
此时则适合在name列上建立单列索引,而
select * from peple where name='jack' and age>20
此时则适合在name和age列上创建多列索引,这样更能够加快查询速度。索引的使用具有最左前缀匹配原则,当判别条件中存在索引的引导列时会使用该索引。假设people表有四个索引nameindex(name),ageindex(age),telindex(tel),mutilindex(name,age,tel)。
select * from peple where name='jack' 会选择使用nameindex索引,而select * from peple where name='jack' and age>20则会选择使用mutilindex,注意一次查询只能使用上面4个索引中的一个索引。对于mutilindex,若判别条件为(name),(name,age),(name,age,tel),(name,tel)等都可以使用该索引,而(age,tel),(tel)都不能够使用该做引。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。