索引是存储引擎用来快速查找记录的一种数据结构,按照实现的方式有不一样的种类,想B-Tree索引,hash索引,空间数据索引和全文索引等。下面主要说一下B-Tree索引和Hash索引。
人们在谈论索引的时候若是没有特别说明,通常指的是B-Tree索引。B-Tree索引是使用B-Tree数据结构来存储索引的。B-Tree一般意味着全部的值是按照顺序存储的。B-Tree树有以下几个特征:
⑴树中每一个结点至多有m 棵子树;
⑵若根结点不是叶子结点,则至少有两棵子树;
⑶除根结点以外的全部非终端结点至少有[m/2] 棵子树;
⑷全部的非终端结点中包含如下信息数据:
(n,A0,K1,A1,K2,…,Kn,An)
其中:Ki(i=1,2,…,n)为关键码,且Ki<Ki+1,html
Ai 为指向子树根结点的指针(i=0,1,…,n),且指针Ai-1 所指子树中全部结点的关键码均小于Ki (i=1,2,…,n),An 所指子树中全部结点的关键码均大于Kn.mysql
n 为关键码的个数。
⑸全部的叶子结点都出如今同一层次上,而且不带信息(能够看做是外部结点或查找失败的结点,实际上这些结点不存在,指向这些结点的指针为空)。 即全部叶节点具备相同的深度,等于树高度。
对于B-Tree索引,存储引擎在查找记录的时候再也不是经过扫描全表来获取须要的数据么人是从索引的根节点进行搜索,根节点的槽中存放了指向子节点的指针,存储引擎根据这些指针向下查找。最后找到叶子节点。叶子节点比较特殊,他的指针指向的是索引的数据。并且不一样的存储引擎实现也不同。在mysql中MyISAM中指针指向的是数据的指针,而在InnoDB中,直接存放的是数据。sql
那么在什么状况下B-Tree可使用索引呢?假设存在一张user表,咱们对(“姓”,“名”,“出生日期”)创建符合索引,那么在B-Tree的key中就是按照姓,名,出生日期顺序存储的,这样方便咱们理解下面这些状况:
1,全值匹配,指的是索引中的全部列进行匹配。好比 where 姓=‘张’ and 名=‘小凡’and 出生年月=‘1990-12-21’;
2,匹配最左前缀。好比查找 姓=‘张’,只能使用第一列。你想若是咱们要名=‘三’,那么能够是‘赵三’,‘李三’索引中先根据姓排序,因此名=‘三’的根本没在一块儿,没法使用索引。
3,匹配列前缀 好比查找‘欧%’;
4,匹配范围值 可使用索引列的第一列。
5,精确匹配某一列,在范围匹配另一列。
根据B-Tree存储的特色,很容易知道有一些状况是没有办法使用索引的。好比以下状况:
1,不是按照索引列最左侧开始查找。
2,跳过中介的列。
3,若是某个列采用范围查找,那么右侧的列都没有办法使用索引。
B-Tree索引有一些独特的好处的,好比在B-Tree树的key中存放了索引列的值,因此若是咱们只须要查询索引列的结果就能够直接使用索引而不须要去查找记录了。这就是覆盖索引的优化。
另外,由于B-Tree索引是有序的,因此除了查找以外,索引还能够用于查询中的order by 排序。
Hash索引
哈希索引是基于哈希表实现的。只有精确匹配索引全部列的的查询才有效。他的实现是存储殷勤会对每一行数据的索引列计算哈希码,并将哈希码和指向该记录的指针维护起来,对于hash相同的,采用链表的方式解决冲突。相似于hashmap。由于索引的结构是十分紧凑的,因此hash索引的查询很快。
可是hash索引也有他的限制:
1,hash索引只包含了哈希值和行指针,索引不能避免读取行,不能使用覆盖索引。
2,hash索引并非按照索引顺序存储的,没法用于排序。
3,hash索引不支持部分或者区域查找,部分列的hash结果是不一样的。
在Mysql中InnoDB引擎有一个特殊的功能叫作自适应哈希索引,他会在内存中基于B-Tree索引的基础上面建立一个哈希索引,这让B-Tree索引页具有了一些哈希索引的优势。
在《高性能的Mysql》这本树中,做者举了一个自定义哈希索引的列子。假设咱们在一个表中大量存储了URL,并且须要根据URL来进行查找。由于URL比较长,这个时候若是咱们使用B-Tree索引来,索引会很是的大。解决的办法是在列表中增长一个列,用来存放URL的哈希值,能够经过CRC32对URL进行计算,并存放在列表中,在查找的时候经过CRC32对url进行计算匹配列表中的hash值。
可是这个地方须要注意hash冲突的问题,因此在查询的时候须要添加url的匹配。
例如:where url_crc=CRC32(“http://www.cnblogs.com/yimixiong/p/7400914.html”) and url=” http://www.cnblogs.com/yimixiong/p/7400914.html”数据结构