以下是网上找的几篇介绍mysql索引的文章:
mysql索引使用示例:
http://www.cnblogs.com/yjl49/archive/2012/02/08/2371926.html
http://www.cnblogs.com/dreamhome/archive/2013/04/16/3025304.html
理解MySQL——索引与优化:(强烈推荐,讲解相对深入)
http://www.cnblogs.com/hustcat/archive/2009/10/28/1591648.html
MySQL 5.6 Reference Manual
http://dev.mysql.com/doc/refman/5.6/en/preface.html
mysql索引的使用傻瓜教程
http://www.php100.com/html/webkaifa/database/Mysql/2013/0316/12223.html
innodb索引(推荐)
http://blog.sina.com.cn/s/blog_9e55238601017ddu.html
一、从索引方法(或索引算法)角度看
mysql中主要有四种类型的索引,分别为:B-Tree 索引,Hash 索引,Full-text 索引和 R-Tree 索引,下面针对这四种索引的基本实现方式及存储结构做一个大概的分析。
1、B-Tree 索引
B-Tree 索引是 MySQL 数据库中使用最为频繁的索引类型,除了 Archive 存储引擎之外的其他所有的存储引擎都支持 B-Tree 索引。不仅仅在 MySQL 中是如此,实际上在其他的很多数据库管理系统中B-Tree 索引也同样是作为最主要的索引类型,这主要是因为 B-Tree 索引的存储结构在数据库的数据检索中有非常优异的表现。Innodb 存储引擎的 B-Tree 索引实际使用的存储结构实际上是 B+Tree,也就是在 B-Tree 数据结构的基础上做了很小的改造,在每一个Leaf Node 上面出了存放索引键的相关信息之外,还存储了指向与该
Leaf Node 相邻的后一个 Leaf Node 的指针信息,这主要是为了加快检索多个相邻 Leaf Node 的效率考虑。
参考文章:http://blog.sina.com.cn/s/blog_9e55238601017ddu.html
在 Innodb 存储引擎中,存在两种不同形式的索引,一种是 Cluster 形式的主键索引(Primary Key),另外一种则是和其他存储引擎(如 MyISAM 存储引擎)存放形式基本相同的普通 B-Tree 索引,这种索引在 Innodb 存储引擎中被称为 Secondary Index。两种索引在Root Node 和 Branch Nodes 方面都还是完全一样的。而 Leaf Nodes 就出现差异了。在 Primary Key中,Leaf Nodes 存放的是表的实际数据,不仅仅包括主键字段的数据,还包括其他字段的数据,整个数据以主键值有序的排列。而
Secondary Index 则和其他普通的 B-Tree 索引没有太大的差异,只是在Leaf Nodes 出了存放索引键的相关信息外,还存放了 Innodb 的主键值。
2、Hash 索引
Hash 索引在 MySQL 中使用的并不是很多,目前主要是 Memory 存储引擎使用,而且在 Memory 存储引擎中将 Hash 索引作为默认的索引类型。
由于 Hash 索引结构的特殊性,其检索效率非常的高,索引的检索可以一次定位,而不需要像 BTree 索引需要从根节点再到枝节点最后才能访问到页节点这样多次 IO 访问,所以 Hash 索引的效率要远高于 B-Tree 索引。
但是 Hash 索引本身由于其实的特殊性也带来了很多限制和弊端,主要有以下这些:
1). Hash 索引仅仅只能满足“=”,“IN”和“<=>”查询,不能使用范围查询;
2). Hash 索引无法被利用来避免数据的排序操作;
由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且 Hash 值的大小关系并不一定和 Hash 运算前的键值的完全一样,所以数据库无法利用索引的数据来避免任何和排序运算;
3). Hash 索引不能利用部分索引键查询;
对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并之后再一起计算 Hash 值,而不是单独计算 Hash 值,所以当我们通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用到;
4). Hash 索引在任何时候都不能避免表扫面;
由于存在不同索引键存在相同 Hash 值的可能,所以即使我们仅仅取满足某个 Hash 键值的数据的记录条数,都无法直接从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较而得到相应的结果。
5). Hash 索引遇到大量 Hash 值相等的情况后性能并不一定就会比 B-Tree 索引高;
3、Full-text 索引
Full-text 索引也就是我们常说的全文索引,目前在 MySQL 中仅有 MyISAM 存储引擎支持,而且也并不是所有的数据类型都支持全文索引。目前来说,仅有 CHAR,VARCHAR 和 TEXT 这三种数据类型的列可以建 Full-text 索引。
Innodb引擎可以通过插件的方式来实现全文索引。
4、R-Tree 索引
R-Tree 索引可能是我们在其他数据库中很少见到的一种索引类型,主要用来解决空间数据检索的问题。
在 MySQL 中,支持一种用来存放空间信息的数据类型 GEOMETRY,且基于 OpenGIS 规范。在MySQL5.0.16 之前的版本中,仅仅 MyISAM 存储引擎支持该数据类型,但是从 MySQL5.0.16 版本开始,BDB,Innodb,NDBCluster 和 Archive 存储引擎也开始支持该数据类型。当然,虽然多种存储引擎都开始支持 GEOMETRY 数据类型,但是仅仅之后 MyISAM 存储引擎支持 R-Tree 索引。
二、聚集索引和非聚集索引
当前,SolidDB和InnoDB是唯一支持聚集索引的存储引擎。InnoDB按照主键进行聚集,如果没有定义主键,InnoDB会试着使用唯一的非空索引来代替。如果没有这种索引,InnoDB就会定义隐藏的主键然后在上面进行聚集。
参考文章:http://lobert.iteye.com/blog/1673540
聚集索引中键值的逻辑顺序决定了表中相应行的物理顺序。
聚集索引确定表中数据的物理顺序。聚集索引类似于电话簿,后者按姓氏排列数据。由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能包含一个聚集索引。但该索引可以包含多个列(组合索引),就像电话簿按姓氏和名字进行组织一样。
聚集索引对于那些经常要搜索范围值的列特别有效。使用聚集索引找到包含第一个值的行后,便可以确保包含后续索引值的行在物理相邻。例如,如果应用程序执行 的一个查询经常检索某一日期范围内的记录,则使用聚集索引可以迅速找到包含开始日期的行,然后检索表中所有相邻的行,直到到达结束日期。这样有助于提高此 类查询的性能。同样,如果对从表中检索的数据进行排序时经常要用到某一列,则可以将该表在该列上聚集(物理排序),避免每次查询该列时都进行排序,从而节 省成本。
当索引值唯一时,使用聚集索引查找特定的行也很有效率。例如,使用唯一雇员 ID 列 emp_id 查找特定雇员的最快速的方法,是在 emp_id 列上创建聚集索引或 PRIMARY KEY 约束。
参考文章:http://www.cnblogs.com/aspnethot/articles/1504082.html
非聚集索引
非聚集索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同。数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置。
非聚集索引中的项目按索引键值的顺序存储,而表中的信息按另一种顺序存储(这可以由聚集索引规定)。对于非聚集索引,可以为在表非聚集索引中查找数据时常用的每个列创建一个非聚集索引。
在数据库中通过什么描述聚集索引与非聚集索引的?
索引是通过二叉树的形式进行描述的,我们可以这样区分聚集与非聚集索引的区别:聚集索引的叶节点就是最终的数据节点,而非聚集索引的叶节仍然是索引节点,但它有一个指向最终数据的指针。
参考文章:http://jingyan.baidu.com/article/e73e26c0f1e82d24acb6a75d.html
三、单列索引和联合索引(多列索引)
单列索引:指的是在一个字段上建立索引。
下面详细讲解联合索引
联合索引,也叫组合索引:索引不仅仅可以基于单个列建立,也可以通过多个列建立,这种索引叫做联合索引。
对于组合索引,官网:http://dev.mysql.com/doc/refman/5.6/en/multiple-column-indexes.html
推荐文章:http://blog.sina.com.cn/s/blog_9e55238601017ddu.html
两个网址中讲解的都非常的详细。
组合索引遵从最左前缀原则。
最左前缀原理:
例如,以表user中的a,b,c三个列建立联合索引。
① 全列匹配: select * from user where a = ? and b =? and c = ?;
全列匹配顾名思义就是戴上了建立索引的三个列的值,这样是可以精确地使用到具体的索引的,即使顺序不同mysql查询优化器会自动调整where语句的顺序(而不是innodb),使之适应索引结构
② 最左前缀匹配: select * from user where a = ? and b =? ;
这样的语句虽然没有提供完全的列值,但是因为索引是从坐车进行连续匹配的,因此也能够使用利用a,b,c三列建立起来的索引。
③ 使用索引精确匹配,中间某个条件未提供。Select * from user where a = ? and c =? ;
这种情况下,虽然a和c都在索引列中,但是因为b不存在,所以无法匹配最左前缀的连接。这种情况下一般有两种解决方式,如果有大量的查询通过这种方式进行,可以考虑在a和c列上建立一个联合索引。另一种方法是通过填坑的方式,即如果b列上的值不多的话(例如枚举,或者简单的bit类型),通过将sql优化成 select * from user where a = ? and b in(?,?,?……) and c = ? 的方式能够提升一部分的性能。
④ 查询没有使用到索引第一列 select * from user where b = ? and c = ?;
这种情况是不符合最左前缀的,无法使用该索引。
⑤ 匹配字符串前缀情况 select * from user where a = ? and b= ? and c like ‘abc%’;
这种情况符合最左前缀,可以使用索引,但如果通配符不是出现在爱末尾,则无法使用。
⑥ 范围查询 select * from user where a > ? and b = ? and c = ?;
这种情况能够使用索引,但是b和c列的索引无法使用到,如果范围查询不是最左前缀或者查询条件中有两个范围列则无法使用。
⑦ 条件中带有函数或者表达式select * from user where a = ? and b = ? and left(c,2) = ‘ba’
虽然和c like ‘ba%’;达到的效果是一致的,但是由于使用了函数,因此无法使用索引。
对于使用了表达式的sql,例如 select * from user where a = ? and b = ? and c -1 =?;
无法使用索引。
对于单列索引和多列索引,很多学者也做了大量的测试,可以参考下面这个链接: