索引,即Index,在MySQL中也称为key。索引如书本的目录,能够帮咱们精肯定位到目的数据。node
在MySQL中,索引是存储引擎层实现的。索引大多使用B树实现,一般是B+树。B+树的特色是,非叶节点只存索引信息,全部的数据信息存在叶子节点。算法上,能够充分利用非叶子节点的信息,下降整棵树的高度,从而减小时间复杂度;实现上,可让整个查找的数据结构更轻量化,更易总体存进内存,提升查找速度。面试
关于B+树,目前百度上有两个版本,即节点含有N个关键字时,有N个/N+1个子节点。有N个子节点时,包含N个子树的定义能够追溯到严蔚敏版《数据结构》;另外一种说法来自《算法导论》,贴一段原话:算法
B-trees are balanced search trees designed to work well on magnetic disks or other direct-access secondary storage devices. B-trees are similar to red-black trees (Chapter 13), but they are better at minimizing disk I/O operations. Many database systems use B-trees, to store information.
Section 18.1. A common variant on a B-tree, known as a B+tree, stores all the satellite information in the leaves and stores only keys and child pointers in the internal nodes, thus maximizing the branching factor of the internal nodes.数据结构 |
以算法导论为准,示意图以下:less
下面用一个具体的例子说明B+树在InnoDB中的实现。有数据表:ide
CREATE TABLE People ( last_name varchar(50) not null, first_name varchar(50) not null, dob date not null, gender enum('m', 'f')not null, key(last_name, first_name, dob) );
该表创建了last_name, first_name, dob的三列联合索引,则其数据存储方式为:函数
从前两个和最后两个例子对比可得出: 索引是按照定义顺序对值进行排序的。形象地,想象你在有三个属性的class中重写compareTo方法。性能
上述方式决定了,B+树索引适用于全键值、键值范围、键前缀查询。具体地,支持如下类型的查询:优化
此外,“覆盖索引”能够在不访问字段的状况下,取出要查询的值;ORDER BY也能够借助索引实现。规则1和2限定了联合索引的列使用范围,规则3和4限定了每一个列可使用索引的方式。在理解了联合索引的存储结构后,并不难总结出上述规则,或者其余(禁止)规则。基于上述实现,B+树的索引存在如下限制:
总结起来,索引列的顺序对性能影响很大。限制3中,范围查询属于匹配列前缀的状况,实际上并不会致使索引失效,属于 MySQL优化器调用存储引擎方式的限制。
这是一种基于哈希表的索引,对每行数据的索引计算出一个哈希码;只有精确匹配索引全部列的查询才有效。索引哈希表的key是哈希值,value是指向对应数据的指针;采用链地址法解决哈希冲突。
基于哈希表实现的索引,结构紧凑,数据量小,查找速度很快,能够用于join操做;同时,有如下局限:
InnoDB能够自适应哈希索引。某些索引或者某索引被频繁使用时,在内存中基于B+树索引为这些列(或前缀)建立一个哈希索引。
InnoDB的作法,给咱们提供了一种快速查询的思路:手动建立hash列做为索引列。
例如,在一个存储url的表中,常常须要作:select id from urlTable where url="http://www.baidu.com"。能够在urlTable中新增url_crc列,使用CRC32作哈希,并对url_crc创建索引,这样查询可写为:select id from urlTable where url="http://www.baidu.com" and url_crc=CRC32("http://www.baidu.com")。注意,url=的条件不能省,须要以此解决哈希冲突。(PS.早年百度经典的URL去重面试题就是用这个思想作的)。
触发器能够实现上述方案:
CREATE TABLE pseudohash ( id int unsigned NOT NULL auto_increment, url varchar(255) NOT NULL, url_crc int unsigned NOT NULL DEFAULT 0, PRIMARY KEY(id) ); DELIMITER // CREATE TRIGGER pseudohash_crc_ins BEFORE INSERT ON pseudohash FOR EACH ROW BEGIN SET NEW.url_crc=crc32(NEW.url); END; // CREATE TRIGGER pseudohash_crc_upd BEFORE UPDATE ON pseudohash FOR EACH ROW BEGIN SET NEW.url_crc=crc32(NEW.url); END; // DELIMITER ;
哈希函数要考虑两个点:哈希值短、冲突少。对于大量冲突的状况,可使用二次哈希;一样的,原始字段的查询条件不能省略。
空间数据索引:MyISAM支持,无须前缀查询,从全部维度进行索引,支持任意组合。
全文索引:基于关键词的索引,不适用where操做,用于MATCH AGAINSST。
聚簇索引、覆盖索引等。