数据库索引的概念:
- 索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速定位数据库表中的特定信息。索引是一种数据结构。
DB在执行一条Sql语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合。如果我们对某一字段增加索引,查询时就会先去索引列表中一次定位到特定值的行,大大减少遍历匹配的行数,所以能明显增加查询的速度。
来分析这张图片,为Col2列建立了索引,该索引是一颗二叉搜索树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针。例如我们要查找表中Col2 = 23时Col1列的值,无索引时就是对表进行全表扫描直到找到23,这样要扫描的行数就是7行,时间复杂度是O(N)。当建立了索引时,数据库引擎先在索引中查找到23这个结点,时间复杂度是O(log2N),然后根据指针直接定位数据库中的位置进行读取,这时只检索了一行(磁盘IO更少,时间效率更高)。
补充:
既然为列增加索引可以提高查询速度,为什么不每一列都增加索引呢?
- 创建索引要耗费时间,这种时间随着数据量的增加而增加。
- 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
- 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
一般要创建索引的列:
- 在经常需要搜索的列上,可以加快搜索的速度
- 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构(主键默认会添加索引)
- 在经常用在连接的列上(MySQL的InnoDB引擎默认物理外键的父列与子列都要创建索引,就是为了加快连接与查找速度)。若无索引,两张表要进行全表扫描进行连接匹配。加了索引后先对索引进行连接匹配,再通过匹配好的索引结点直接定位数据库。
一般不创建索引的列:
- 在查询中很少使用或者参考的列不应该创建索引
- 对于那些定义为TEXT, IMAGE等数据类型的列不应该增加索引。这是因为,这些列的数据量(占用字节)相当大。
- 需要频繁修改的列,因为修改数据时要对索引进行动态维护。
- 一旦查找就基本要查找表中大部分行的,这时也没有建立索引的必要。
说了那么多,下面要进行测试检验了。
test3表中有一个id字段,无任何约束与索引,有10个记录:
查找id为10的记录:
从执行计划中可以看出,本次查询对表test3进行了全表扫描,其中扫描的行数是10行。
这时,为id列建立一个名字为index_of_id的索引:
进行同样的查询:
得到了相同的结果,从执行计划中可以看出,本次查询实际用到索引index_of_id(key)。且只对数据库中进行了1行的检索。
再做一次测试,上面是对等号的测试,这次对大于号进行测试。
先去掉id列的索引:
查找id大于9的记录:
得到一条记录,且对数据表进行了全表扫描,扫描了10行,这是理所当然的结果。
这时,再为id列建立索引:
进行同样的查询:
同样也使用了索引,只检索了表中1行数据。
但是,当查询id大于8的时候:
发现虽然使用了索引index_of_id查找,但是却检索了数据表中10行的记录。
这说明,索引有时候会失效!
关于索引失效,可以查看以下两篇博客: