一、索引的优缺点?
优点:建立索引可以有效缩短数据的检索时间,包括条件查询、连接查询、排序和分组。
缺点:索引占据数据库的物理存储空间,创建索引和维护索引需要时间成本,降低表的增删改的效率。
二、聚集索引和非聚集索引的区别
1)聚集索引数据行的物理顺序与列值(这里是主键)的逻辑顺序相同,一个表中只能拥有一个聚集索引。非聚集索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。
2)聚集索引在叶子节点存储的是表中行记录的全部数据,而非聚集索引在叶子节点存储的是索引列和主键。
使用非聚集索引查询出数据时,拿到叶子上的主键再去查到想要查找的数据,这个过程叫做回表,因此非聚集索引也被叫做二级索引(辅助索引)。
回表:
辅助索引的叶子节点并不包含行记录的全部数据,而是键值和聚集索引键(主键),数据库根据索引找到了指定的记录所在行后,还需要根据主键再次到数据块里取数据的操作就叫回表
ps:通过非聚集索引获得主键,再根据主键去聚集索引中获取数据(回表)。
菜单表(id,name,orderby,create_time)中,id为主键,并为name字段创建索引,如下:
当查询的字段包含除了where条件中的索引键和主键之外的其他字段:
explain select * from menu where name='菜单1'
explain select id,name,url from menu where name='菜单1'
结果如下:
如果只查询where条件中的索引键或主键时
explain select id from menu where name='菜单1'
explain select name from menu where name='菜单1'
explain select id,name from menu where name='菜单1'
结果如下:
对比这两个结果
1)因为where条件相同,所以查询计划的key相同,都走了name上非聚集索引idx_menu_name,
2)因为查询的字段不同,所以Extra不同,第一个是null,代表回表,而第二个是只查询id或name时,Extra为【using index】,并没有回表,使用的索引已经覆盖了需要查询的字段,只通过索引就获取到了需要的字段。
当索引的叶子节点包含了要查询的数据,那么就不用回表查询了,这个叫做覆盖索引。
当执行计划出现Extra中包含Using index,说明MySQL正在使用覆盖索引,它只扫描索引的数据,比按索引次序全表扫描的开销少很多。
前缀索引由于有length限制,叶子节点保存的并不是完整的键值,也就谈不上什么覆盖索引了。
ps:插两道题
{
1、问:select *和select字段的区别?
1)从网速,带宽方面考虑。
2)覆盖索引。
2、问:前缀索引的缺点?
1)从索引选择性上考虑
2)无法走覆盖索引,只能回表
}
三、 联合索引和多个单列索引
上文中,我们只查询id和name字段,使用覆盖索引的原理,避免了回表,但真实的应用场景,恰恰是需要返回id、name和url三个字段,mysql中的单个查询只能用一个索引,因此,即使url上也有索引,也会回表。
name和url上分别有各自的索引,如下
执行查询语句,检索name和url两个字段:
explain select name,url from docker_mysql.menu where url='url1' and name='菜单1'
结果如下,
分析:
结果显示,可能的key有idx_menu_name和idx_menu_url,但真正执行时走的key为idx_menu_name,而该索引中的数据只有name和主键,并没能覆盖字段url。
在name和url上分别创建单列索引并不能满足覆盖索引的条件,只有在name和url创建一个联合索引时,才能同时通过索引同时获取两列的值,从而避免回表。
索引可以简单如一个列(a),也可以复杂如多个列(a,b,c,d),即联合索引。
在name和url上创建一个联合索引
再次执行查询语句
Extra为Using index,说明使用了覆盖索引。
1)索引最左匹配原则
- 索引可以简单如一个列(a),也可以复杂如多个列(a,b,c,d),即联合索引。
- 联合索引只能用于查找key是否存在(相等),遇到范围查询
(>、<、between、like
左匹配)等就不能进一步匹配了,后续退化为线性查找。 - 因此,列的排列顺序决定了可命中索引的列数。
eg:
如有索引(a,b,c,d),查询条件a=1 and b=2 and c>3 and d=4,则会在每个节点依次命中a、b、c,无法命中d。(很简单:索引命中只能是相等的情况,不能是范围匹配)
2)=、in自动优化顺序
不需要考虑=、in等的顺序,mysql会自动优化这些条件的顺序,以匹配尽可能多的索引列。
eg:
如有索引(a,b,c,d),查询条件c>3 and b=2 and a=1 and d<4与a=1 and c>3 and b=2 and d<4等顺序都是可以的,MySQL会自动优化为a=1 and b=2 and c>3 and d=4,依次命中a、b、c。
ps:插一道题
{
联合索引和多个单列索引的区别
单个多列组合索引和多个单列索引的检索查询效果不同,因为在执行SQL时,MySQL只能使用一个索引,会从多个单列索引中选择一个限制最为严格的索引。
}
四、重复索引与冗余索引
重复索引:表示一个列或者顺序相同的几个列上建立的多个索引。
冗余索引:两个索引所覆盖的列重叠
a、b两个字段上同时创建索引(a,b)和(a)是冗余索引
五、and/or/join/in/exist/like/<>
innodb下对索引的学习就到此为止了,作为一个入门级的系列文章,重点是在于数据库相关知识的了解与简单应用。在以后的文章肯定会涉及到数据库相关的更高层次的应用,到时候还是会回过头来,做更加深入的研究的。