索引:个人的理就是,索引是一种加快查询数据的数据结构。
主键索引在InnoDB存储引擎中是最常见的索引类型,一个表都会有一个主键索引,它索引的字段不允许为空值,并且唯一。
在创建表的时候,可以通过RIMARY KEY指定主键索引,在InnoDB存储引擎中,若是创建表的时候没有主观创建主键索引,Mysql就会看表中是否有唯一索引,有,就会指定「非空的唯一索引」为主键索引;没有,就会默认生成一个6byte空间的自动增长主键作为主键索引,可以通过select _rowid from 表名查询的是对应的主键值.。
MyISAM储存引擎是可以不存在主键索引,MyISAM和InnoDB储存数据的结构方式有明显的区别
唯一索引与主键索引的区别就是,唯一索引允许为空,若是在组合索引中,只要创建的列值是唯一的
唯一索引在实际中更多的是用来保证数据的唯一性,如仅仅要数据能够快速查询,可以使用普通索引
创建唯一索引的方式有三种。 (1)在创建表的时候指定:
CREATE TABLE user( id INT PRIMARY KEY NOT NULL, name VARCHAR(16) NOT NULL, UNIQUE unique_name (name(10)) ); . (2)在表创建后创建: CREATE UNIQUE INDEX unique_name ON user(name(10)); . (3)通过修改表结构创建,如下sql: ALTER user ADD UNIQUE unique_name ON (name(10))普通索引的唯一作用就是加快数据的查询,一般对查询语句WHERE和ORDER BY后面的字段创建普通索引。
创建普通索引的方式也有三种,和创建唯一索引基本一样,只是把UNIQUE换成INDEX: (1)创建表的时候创建
CREATE TABLE user( id INT PRIMARY KEY NOT NULL, name VARCHAR(16) NOT NULL, INDEX index_name (name(10)) ); . (2)创建表后创建 CREATE INDEX INDEX index_name ON user(name(10)); . (3)修改表结构创建 ALTER user ADD INDEX index_name ON (name(10))组合索引即用多个字段创建一个索引,组合索引能够避免「回表查询」,相对于多字段的单列索引,组合索引的查询效率更高。
创建组合索引(联合索引)的方式和创建普通索引的方式一样,只不过字段的数目多了,如下sql创建,只列举修改表结构的方式:
ALTER TABLE employee ADD INDEX name_age_sex (name(10),age,sex);回表查询简单来说「通过二级索引查询数据,得不到完整的数据行,需要再次查询主键索引来获得数据行」。
InnoDB存储引擎中,索引分为 「聚簇索引」和「二级索引」,主键索引就是聚簇索引,其它索引为二级索引。
聚簇索引中的叶子节点保存着完整的数据行,而二级索引的叶子节点并不是保存完整的数据行。
上面提到InnoDB表是一定要有主键索引的,虽然索引占据空间,但是索引符合二分查找的算法,查找数据非常的快。
假设一张表里面有主键索引id,和普通的索引name,那么在InnoDB中就会存在两棵B+Tree,一棵是主键索引树:(在主键索引树中的叶子节点存储的是完整的数据行) 另外一棵是name字段的二级索引树: 倘若执行:select name, age, sex from 表名 where id =‘as’;会先执行二级索引的查询,当查询name='as’时,得到主键为50,再根据主键查询主键索引树,得到完整的数据行,执行流程如下:
索引覆盖就是「索引的叶子节点已经包含了查询的数据,没必要再回表进行查询。」
常见的方式就是「建立组合索引(联合索引)「进行」索引覆盖」
假如还是执行:select name, age, sex from employee where id =‘as’;因为普通索引只有name字段才建立了索引,这必然会导致回表查询。
为了提高查询效率,就(name)「单列索引升级为联合索引」(name, age, sex)就不同了。
因为建立的联合索引,在二级节点的叶子阶段就会同时存在name, age, sex三个的值,一次性就会获得所需要的数据,这样就避免了回表,但是所有的方案都不是完美的。
若是这个联合索引哪一天某一个数据行的name值改变了或者age改变了,我就需要同时维护主键索引和联合索引两棵树,这样的维护成本就高了,性能开销也大了。
相比之前数据的改变,我只需要维护主键索引即可,联合索引的创建就导致了需要同时维护两棵树,这样就会影响插入、更新数据的操作,所以并没有哪种方案是完美的。
上图所示,对于联合索引中name字段是放在最前面的,所以name是完全有序的,但是age字段就不是有序的,只有当name相同,例如:name='bc’此时age字段的索引排序才是完全有序的。
所以你会发现,在联合索引中你只有使用以下的规则的方式查询才会使用到索引: name,age,sex name,age name
因为Mysql的底层有查询优化器,会判断sql执行的时候若是使用全表扫描的效率比使用索引的效率更高,就会使用全表扫描。
假如查询的时候使用age>=23,sex='男';两个字段作为查询条件,但是没有使用name字段,因为在name不知情的条件下,对于age是无序的。
对于age>=23条件可能在很多的name不同中都有符合条件的出现,所以就没有办法使用索引,这也是索引实现的原因,一定要遵循「查找有序,充分的利用索引的有序性」。
假如你是分别在name,age,sex三个字段中分别建立三个单列索引,就相当于建立三颗索引树,那么它的查询效率,比我们使用一棵索引树查询效率就可想而知了。
有一种情况即使使用到了最左边的name字段也不会使用索引,例如:WHERE name like '%d%';这种like条件的模糊查询会使索引失效。
我们可以这样理解,「查询字符串也是遵循最左前缀原则的」,字符串的查询是对字符串里面的字符一个一个的匹配,「若是字符串最左边为%表示一个不确定的字符串,那么是没办法利用到索引的有序性」。
但是若是修改为 :WHERE name like 'd%';就可以使用索引,因为最左边的字符串是确定的,这种称为「匹配列前缀」。
实际业务场景中联合索引的创建,「我们应该把识别度比较高的字段放在前面,提高索引的命中率,充分的利用索引」。
聚簇索引和非聚簇索引是相对于存储引擎的概念,范围比较大,包含上面所提到的索引类型。
「聚簇索引就是叶子节点中存储的就是完整的行数据,索引和数据存储在一起;而非聚簇索引的索引文件和数据文件是分开的,所以查询数据会多一次查询」。
因此聚簇索引的查询速度会快于非聚簇索引的查询速度,再Mysql的村相互引擎中,「InnoDB支持聚簇索引,MyISAM不支持聚簇索引,MyISAM支持非聚簇索引」。