索引是存储引擎用于快速找到数据记录的一种数据结构,好比一本教科书的目录部分,通过目录中找到对应文章的页码,便可快速定位到需要的文章。MySQL也是一样的道理,进行数据查找时,首先查看查询条件是否命中某条索引,符合则通过索引查找相关数据,如果不符合则需要全表扫描,即需要一条一条地查找记录,知道找到与条件符合的记录。
数据库没有索引的情况下,数据分布在硬盘不同的位置上面,读取数据时,摆臂需要前后摆动查找数据,操作非常消耗时间。如果数据顺序摆放,那么也需要从1到6行按顺序读取,相当于进行6次IO操作,依旧非常耗时。 如果我们不借助任何索引结构1帮助我们快速定位数据的话,我们查找col2=89这条记录,就要逐行去查找、去比较。从col2=34开始,进行比较,发现不是,继续下一行。我们当前的表只有不到10行数据,但如果表很大的话,有上千万条数据,就意味着要做很多很多次磁盘I/O才能找到。现在要查找col2=89这条记录,cpu必须先去磁盘查找这条记录,找到之后加载到内存,再对数据进行处理。这个过程最耗时间的就是磁盘IO(涉及到磁盘的旋转时间(速度较快)+磁头的寻道时间(速度慢+费时))。
假如给数据使用二叉树这样的数据结构进行存储,如下图所示:
对字段col2添加索引,相当于在硬盘上为col2维护了一个索引的数据结构,即二叉搜索树。二叉搜索树的每个结点存储的是**(K,V)结构**,key是col2,value是该key所在行的文件指针(地址)。比如:该二叉搜索树的根节点就是(34,0x07)。现在对col2添加了索引,这时再去查找col2=89这条记录的时候会先去查找该二叉搜索树(二叉树的遍历查找)。读34到内存,89>34;继续右侧数据,读89到内存,89==89;找到数据返回。找到之后的根据就是当前结点的value快速定位到要查找的记录对应的地址。我们可以发现,只需要查找两次就可以定位到记录的地址,查询速度就提高了。
建索引的目的:减少磁盘IO的次数,加快查询速率。
MYSQL官方对索引的定义为:索引(Index)是帮助MySQL高速获取数据的数据结构。
索引的本质:索引是数据结构。你可以简单理解为“排好序的快速查找数据结构”,满足特定查找算法。这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高级查找算法。
索引是在存储引擎中实现的,因此每种存储引擎的索引不一定完全相同,并且每种存储引擎不一定支持所有索引类型。同时,存储引擎可以定义每个表的最大索引数和最大索引长度。所有存储引擎支持每个表至少16个索引,总索引长度至少为256字节。有些存储引擎支持更多的索引数和更大的索引长度。
优点
缺点
先来看一个精准匹配的例子:
select [列名列表] FROM 表名 WHERE 列名=xxx;
(1)在一个页中的查找
假设目前表中的记录比较少,所有的记录都可以被存放到一个页中,在查找记录的时候可以根据搜索条件的不同分为两种情况:
(2)在很多页中查找
大部分情况下我们表中存放的记录都是非常多的,需要好多的数据页来存储这些记录。在很多页中查找记录的话可以分为两个步骤:
在没有索引的情况下,不论是根据主键列或者其他列的值进行查找,由于我们并不能快速的定位到记录所在的页,所以只能从第一个页沿着双向链表一直往下找,在每一个页中根据我们上面的查找方式去查找指定的记录。因为要遍历所有的数据页,所以这种方式显然是超级耗时的。如果一个表有一亿条记录呢?此时索引应运而生。
建一个表:
CREATE TABLE index_demo(
c1 INT,
c2 INT,
C3 CHAR(1),
PRIMARY KEY(C1)
)ROW_FORMAT=Compact;
(1)一个简单的索引设计方案