支持多种索引算法,如BTree索引,哈希索引,全文索引等等。
如果表没有设置索引,InnoDB 会自动在主键上创建隐藏的聚簇索引! pic

存储方式

b+树要求把真实的数据放到叶子节点而不是内层节点,一旦放到内层节点,磁盘块的数据项会大幅度下降,导致树增高。当数据项等于1时将会退化成线性表。

索引类型

mysql索引规则中要求复合索引要想使用第二个索引,必须先使用第一个索引。(而且第一个索引必须是等值匹配)
innodb 中每张表有且仅有一个聚簇索引,剩下的都是非聚簇索引。对于非聚簇索引,叶子节点并不会包含行记录的全部数据,而是保存指向聚簇索引中某一条记录的指针。
聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。(即回表)

访问类型

表示MySQL在表中找到所需行的方式,又称“访问类型”。 常用的类型有: ALL, index, range, ref, eq_ref, const, system, NULL(从左到右,性能从差到好)

ALL:

Full Table Scan, MySQL将遍历全表以找到匹配的行

index:

Full Index Scan,index与ALL区别为index类型只遍历索引树。要想用到这种类型的索引,对这个索引并无特别要求,只要是索引,或者某个复合索引的一部分,mysql都可能会采用index类型的方式扫描。但是呢,缺点是效率不高,mysql会从索引中的第一个数据一个个的查找到最后一个数据,直到找到符合判断条件的某个索引。

range:

只检索给定范围的行,使用一个索引来选择行

ref:

表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值。这种类型表示mysql会根据特定的算法快速查找到某个符合条件的索引,而不是会对索引中每一个数据都进行一一的扫描判断,也就是所谓你平常理解的使用索引查询会更快的取出数据。而要想实现这种查找,索引却是有要求的,要实现这种能快速查找的算法,索引就要满足特定的数据结构。简单说,也就是索引字段的数据必须是有序的,才能实现这种类型的查找,才能利用到索引。

eq_ref:

类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件

const、system:

当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system

NULL:

MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。

创建原则

  • 1.最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配, 比- 如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,- c)的索引则都可以用到,a,b,d的顺序可以任意调整。
  • 2.=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式
    1. 尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就 是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条 记录
    1. 索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本 太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’);
    1. 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可
    1. 索引字段要尽量的小;
    1. 用 exists 代替 in
    1. 使用 varchar/nvarchar 代替 char/nchar
    1. 能用DISTINCT的就不用GROUP BY

避免Like的参数以通配符开头,否则数据库引擎会放弃使用索引而进行全表扫描 where条件不符合最左前缀原则时,无法使用联合索引; 避免使用!= 或 <>(同!=)操作符,否则数据库引擎会放弃使用索引而进行全表扫描。使用>或<会比较高效。 避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描 避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描 避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描 避免select * 任何在Order by语句的非索引项或者有计算表达式都将降低查询速度。 提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉

select * from *** limit 10 1000: select * from *** where offset>1000 limit 10; 性能比对(索引使用)

B+tree (叶子节点额外增加指针构成链表,提升区间查询效率 myISAM:数据与索引分离,非聚集索引;