MySQL只走一个索引,还是会索引合并?索引下推会怎样?

微信公众号:molashaonian

MySQL是否每次只能使用一个索引?

答案当然不是的,MySQL每次可以使用多个索引,即 index merge(索引合并),但大多数情况下都只会使用一个索引,那这是为什么咧?

1. 为什么会有index merge

  • MySQL5.0之前,一个表一次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。但是从5.1开始,引入了 index merge 优化技术,对同一个表可以使用多个索引分别进行条件扫描
  • 我们的 where 中可能有多个条件(或者join)涉及到多个字段,它们之间进行 AND 或者 OR,那么此时就有可能会使用到 index merge 技术。index merge 技术如果简单的说,其实就是:对多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union)
  • 索引合并是通过多个range类型的扫描并且合并它们的结果集来检索行的。仅合并来自单个表的索引扫描,而不是跨多个表的索引扫描。合并会产生底层扫描的三种形式:unions(合并)、intersections(交集)、unions-of-intersections(先取交集再合并)
  • 索引合并详细讲解可参考文末推荐阅读

2. 为什么很少见index merge

  • 与其说是“数据库查询只能用到一个索引”,倒不是说是 和全表扫描/只使用一个索引的速度比起来,去分析两个索引二叉树更加耗费时间,所以绝大多数情况下数据库都是是用一个索引。
  • 如这条语句:
select count(1) from table1 where column1 = 1 and column2 = 'foo' and column3 = 'bar'
  • 我们来想象一下当数据库有N个索引并且查询中分别都要用上他们的情况:
    查询优化器(用大白话说就是生成执行计划的那个东西)需要进行N次主二叉树查找[这里主二叉树的意思是最外层的索引节点],此处的查找流程大概如下:
    查出第一条column1主二叉树等于1的值,然后去第二条column2主二叉树查出foo的值并且当前行的coumn1必须等于1,最后去column主二叉树查找bar的值并且column1必须等于1和column2必须等于foo。
    如果这样的流程被查询优化器执行一遍,就算不死也半条命了,查询优化器可等不及把以上计划都执行一遍,贪婪算法(最近邻居算法)可不允许这种情况的发生,所以当遇到以下语句的时候,数据库只要用到第一个筛选列的索引(column1),就会直接去进行表扫描了。
  • 所以与其说是数据库只支持一条查询语句只使用一个索引,倒不如说N条独立索引同时在一条语句使用的消耗比只使用一个索引还要慢。
    所以如上条的情况,最佳推荐是使用index(column1,column2,column3) 这种联合索引,此联合索引可以把b+tree结构的优势发挥得淋漓尽致:
    一条主二叉树(column=1),查询到column=1节点后基于当前节点进行二级二叉树column2=foo的查询,在二级二叉树查询到column2=foo后,去三级二叉树column3=bar查找。
  • 当然建了联合索引也需要看数据的分布,索引的可用度高低,尽量把区分度高的字段放前面,或者根据实际的业务场景来做出对字段的先后排序。

索引下推会怎样?

  • 索引下推(index condition pushdown )简称ICP,在Mysql5.6的版本上推出,用于优化查询。
  • 在不使用ICP的情况下,在使用非主键索引(又叫普通索引或者二级索引)进行查询时,存储引擎通过索引检索到数据,然后返回给MySQL服务器,服务器然后判断数据是否符合条件 。
  • 在使用ICP的情况下,如果存在某些被索引的列的判断条件时,MySQL服务器将这一部分判断条件传递给存储引擎,然后由存储引擎通过判断索引是否符合MySQL服务器传递的条件,只有当索引符合条件时才会将数据检索出来返回给MySQL服务器 。
  • 索引条件下推优化可以减少存储引擎查询基础表的次数,也可以减少MySQL服务器从存储引擎接收数据的次数。
  • 可以使用explain查看是否使用索引下推,当Extra列的值为Using index condition,则表示使用了索引下推。

推荐阅读

MySQL 优化之 index merge(索引合并)
MySQL 8.0索引合并
Mysql性能优化:什么是索引下推?
使用MySQL 5.7虚拟列提高查询效率
Java 全栈知识体系

下篇笔录

SQL优化思想汇总

molashaonian

molashaonian

MySQL索引有多种类型,常见的包括: 1. B-Tree索引是一种常见的索引类型,用于等值查找和范围查询。它通过将索引键值按顺序存储在B-Tree数据结构中,以提供高效的查找和排序。 2. 哈希索引:适用于等值查找,但不支持范围查询。它将索引键值计算为哈希值,并将其存储在哈希表中,以实现快速的查找操作。 3. 全文索引:用于对文本内容进行全文搜索。它可以在文本中查找关键词,并返回匹配的结果。 4. 空间索引:用于支持空间数据类型的查询,例如地理位置数据。 关于索引的结构,常见的是B-Tree索引结构。B-Tree索引使用平衡树的数据结构,其中每个节点存储多个索引键值,并按照键值的顺序进行排序。这种结构使得在查找、插入和删除操作时能够高效地定位到目标数据。 回表(Index Lookups)是指当使用非聚集索引进行查询时,如果需要获取其他列的数据,则需要通过回表操作访问主索引或聚集索引来获取完整的行数据。这增加额外的IO开销。 覆盖索引(Covering Index)是指查询所需的数据可以完全通过索引来获取,而不需要回表操作。当查询只需要索引列的数据时,通过覆盖索引可以减少IO开销,提高查询性能。 索引下推Index Condition Pushdown)是MySQL 5.6版本引入的优化技术。它可以在B-Tree索引中对谓词进行评估,并尽可能地减少回表操作。通过将索引列上的谓词下推到存储引擎层,在索引上进行过滤,可以减少不必要的IO开销和数据传输。 这些索引类型和结构的选择和使用MySQL的查询性能产生重要影响,根据具体的业务需求和查询模式,选择合适的索引类型和优化策略是提高MySQL性能的关键。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值