跟着项目学sql(六) 索引(下)

版权声明:本文为博主原创文章,未经博主允许不得转载。博客地址: https://blog.csdn.net/m0_37057454/article/details/82836179

一、索引的优缺点?

优点:建立索引可以有效缩短数据的检索时间,包括条件查询、连接查询、排序和分组。

缺点:索引占据数据库的物理存储空间,创建索引和维护索引需要时间成本,降低表的增删改的效率。

二、聚集索引和非聚集索引的区别

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下对索引的学习就到此为止了,作为一个入门级的系列文章,重点是在于数据库相关知识的了解与简单应用。在以后的文章肯定会涉及到数据库相关的更高层次的应用,到时候还是会回过头来,做更加深入的研究的。

猜你喜欢

转载自blog.csdn.net/m0_37057454/article/details/82836179