Using Where,Using index,Using index condition

这篇具有很好参考价值的文章主要介绍了Using Where,Using index,Using index condition。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

首先回顾一下这三个的定义

定义回顾

  • Using where
    当有where条件,但是不能使用索引或者使用索引后仍需扫描全表或者索引树判断条件的情况,简单来说,有效的where条件就Using where。
  • Using index
    索引覆盖,索引树已包含所有需要的数据,无需回表查询
  • Using index condition
    官方文档:https://dev.mysql.com/doc/refman/8.0/en/index-condition-pushdown-optimization.html
    索引条件下推(Index Condition Pushdown,ICP)是MySQL使用索引的情况的优化。
    简单来说,在服务器需要扫描表的情况下
    当没有ICP时,存储引擎扫描可以明确地使用索引的条件,将符合条件的记录返回给服务器。
    当使用ICP时,只要条件可以在索引上判断出来,就由存储引擎在索引树上完成判断,再将符合条件的记录返回给服务器。
    ICP可以减少存储引擎必须访问基本表的次数以及服务器必须访问存储引擎的次数,这是是否使用ICP的最可靠的判断条件

ICP有以下条件限制:

  • 当type为ref、eq_ref和ref_or_null且需要访问完整表行
  • InnoDB或MyISAM引擎
  • 对于InnoDB来说,ICP只适用于二级索引,可以减少全表扫描从而减少IO次数。对于聚集索引,数据和索引都已经在InnoDB缓冲池中,使用ICP不能减少IO操作。
  • 虚拟列上的二级索引不支持ICP
  • 子查询条件不能下推
  • 不能使用存储函数,存储引擎不能调用这些函数
  • 触发条件不能被下推

是否启用ICP
SET optimizer_switch = ‘index_condition_pushdown=off’;
SET optimizer_switch = ‘index_condition_pushdown=on’;

实战分析

数据库来自MySQL官方employees库

表结构如下:
MySQL8.0.19

CREATE TABLE `employees` (
  `emp_no` int NOT NULL,
  `birth_date` date NOT NULL,
  `first_name` varchar(14) NOT NULL,
  `last_name` varchar(16) NOT NULL,
  `gender` enum('M','F') NOT NULL,
  `hire_date` date NOT NULL,
  PRIMARY KEY (`emp_no`),
  KEY `index_all` (`birth_date`,`last_name`,`first_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

birth_date, last_name, first_name三列联合索引,编码utf8

无条件覆盖索引

explain
select emp_no, first_name, last_name
from employees;

+----+-------------+-----------+------------+-------+---------------+-----------+---------+------+--------+----------+-------------+
| id | select_type | table     | partitions | type  | possible_keys | key       | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+-----------+------------+-------+---------------+-----------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | employees | NULL       | index | NULL          | index_all | 97      | NULL | 299423 |   100.00 | Using index |
+----+-------------+-----------+------------+-------+---------------+-----------+---------+------+--------+----------+-------------+

type为index,扫描整个索引树,服务器层不需要再判断条件,所以Extra只有Using index
使用三列,key_len = 3 + (14 * 3 + 2) + (16 * 3 + 2) = 97

有条件覆盖索引

explain
select emp_no, last_name
from employees
where birth_date = '1999-09-09';

+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | employees | NULL       | ref  | index_all     | index_all | 3       | const |    1 |   100.00 | Using index |
+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+

满足最左匹配原则,且非唯一索引,故type为ref,走覆盖索引,Using index
key_len = 3

不满足最左匹配

explain
select emp_no, first_name
from employees
where last_name like '%达到%';

+----+-------------+-----------+------------+-------+---------------+-----------+---------+------+--------+----------+--------------------------+
| id | select_type | table     | partitions | type  | possible_keys | key       | key_len | ref  | rows   | filtered | Extra                    |
+----+-------------+-----------+------------+-------+---------------+-----------+---------+------+--------+----------+--------------------------+
|  1 | SIMPLE      | employees | NULL       | index | NULL          | index_all | 97      | NULL | 299423 |    11.11 | Using where; Using index |
+----+-------------+-----------+------------+-------+---------------+-----------+---------+------+--------+----------+--------------------------+

where条件不满足最左匹配,但是select的列在索引树中可以全部找到,故Using index,并且type为index,存储引擎扫描整个索引树,找到满足last_name like '%达到%'的数据(where条件有效),返回给服务器,服务器再过滤不需要的字段。
因为使用了整个联合索引,key_len = 97

如果select了不在联合索引的字段,则不能使用覆盖索引,只有Using where了。

索引下推

explain
select emp_no, first_name, hire_date
from employees
where birth_date = '199-09-09'
  and last_name like '%达到%';

+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------+
| id | select_type | table     | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | employees | NULL       | ref  | index_all     | index_all | 3       | const |    1 |    11.11 | Using index condition |
+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------+

首先明确一点,这条SQL必须访问基本表,因为有hire_date字段,所以一定没有Using index。
满足最左匹配,birth_date字段走索引,但是last_name不能走索引。
在有ICP的情况下,last_name的判断由存储引擎在索引树上完成,返回给服务器后,因为有hire_date字段,服务器访问基本表获取所有数据。

当没有ICP情况下,last_name由服务器完成判断,只有Using where,服务器读取基本表的部分行可能是不满足条件的。

注意:Using index condition下推的条件并没有用到索引,而是全部扫描,所以key_len不计算在内,所谓用到索引,就是利用了B+树查找的特性

+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | employees | NULL       | ref  | index_all     | index_all | 3       | const |    1 |    11.11 | Using where |
+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+

去掉hire_date

explain
select emp_no, first_name
from employees
where birth_date = '199-09-09'
  and last_name like '%达到%';

+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+
| id | select_type | table     | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra                    |
+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+
|  1 | SIMPLE      | employees | NULL       | ref  | index_all     | index_all | 3       | const |    1 |    11.11 | Using where; Using index |
+----+-------------+-----------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+

没有hire_date,服务器不需要访问基本表,ICP优化也就没必要了。文章来源地址https://www.toymoban.com/news/detail-790536.html

到了这里,关于Using Where,Using index,Using index condition的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 已解决ValueError: If using all scalar values, you must pass an index

    已解决(pandas创建DataFrame对象失败)ValueError: If using all scalar values, you must pass an index 粉丝群里面的一个粉丝用pandas创建DataFrame对象,但是发生了报错(跑来找我求助,然后顺利帮助他解决了,顺便记录一下希望可以帮助到更多遇到这个bug不会解决的小伙伴),报错信息和代码

    2024年02月09日
    浏览(71)
  • where怎么等于多个值,sql where多个值

    在SQL中,可以使用IN和OR操作符来匹配多个值,以在WHERE语句中执行过滤。以下是一些示例: 使用IN操作符匹配多个值 可以使用IN操作符来匹配多个可能的值,如下所示: SELECT * FROM 表名 WHERE 字段名 IN (\\\'值1\\\', \\\'值2\\\', \\\'值3\\\', ...); 示例: SELECT * FROM Users WHERE Country IN (\\\'China\\\', \\\'Japan\\\',

    2024年02月06日
    浏览(47)
  • SQL ASNI where from group order 顺序 where和having,SQL底层执行原理

    SQL语句执行顺序: from–where–group by --having — select -- order 第一步:from语句,选择要操作的表。 第二步:where语句,在from后的表中设置筛选条件,筛选出符合条件的记录。 第三步:group by语句,把筛选出的记录进行分组。 第四步:having语句,设置条件筛选分组后的数据。

    2024年02月14日
    浏览(54)
  • ORM 自定义sql,where条件变量值为null,转为:where remark=null是不对的

    ORM 自定义sql,where条件变量值为null,转为:where remark=null是不对的 该如何解决呢? 例子如下: 需要在变量的值为null时,改为: remark is null 这是SQL的语法. 使用ORM自定义sql, 在where条件,使用remark=#{remark @toIsNULL1}才是对的. 代码参考: https://gitee.com/automvc/bee-exam Bee,一个简单易用,功能强大的

    2024年02月12日
    浏览(56)
  • Numpy中where的理解

    首先numpy中where有两种用法。 一种是numpy.where(条件,满足条件值,不满足条件值)。 一种是numpy.where(条件)。 第一种:numpy.where(条件,满足条件值,不满足条件值)。 第二种:numpy.where(条件)。 (array([0, 1, 1], dtype=int64), array([0, 0, 1], dtype=int64)) 第一个array([0, 1, 1]中的0代表数组中的

    2023年04月08日
    浏览(31)
  • Mybatis中where 1=1 浅析

    在一些集成mybatis的工程中经常看到where1=1 的代码,也有同事问我,这样写有什么用,下面对其进行简单的分析记录一下。 看下面这样一段xml中的代码 上面的代码很简单,就是查询符合条件的总条数,在mybatis中常用到if标签判断where子句后的条件,为防止首字段为空导致sql报

    2024年02月14日
    浏览(46)
  • SQL中的where语句的使用

    `WHERE`语句用于在SQL查询中过滤行,只返回满足特定条件的行。下面是一些常用的`WHERE`语句的例子,假设有三个表:`users`,`products`和`orders`。 1. 简单的WHERE子句 这条语句将从`users`表中选择所有年龄大于18岁的用户。 2. 使用AND和OR运算符的WHERE子句 这条语句将从`products`表中选

    2024年02月16日
    浏览(50)
  • 【知识点】np.where()用法

    目录 一、基本知识 二、具体实例 1.np.where(condition,x,y) (1)示例1: (2)示例2: (3)示例3: 2. np.where(condition) 总结 np.where 函数是三元表达式 x if condition else y 的向量化版本,它有两种用法: 1.np.where(condition,x,y) 当where内有三个参数时,第一个参数表示条件,当条件成立时

    2024年02月01日
    浏览(36)
  • MyBatis 动态SQL之<where>标签-

    where 标签主要用来简化 SQL 语句中的条件判断,可以自动处理 AND/OR 条件。 在if标签和choose-when-otherwise标签的案例中,SQL语句加入了一个条件’1=1’,它既保证了where后面的条件成,页避免了where后面出现的第一个词语是and 或者or之类的。 假设把条件‘1=1’去掉,可以出

    2024年02月11日
    浏览(48)
  • Python中np.where()的使用

    np.where() 是NumPy库中一个非常有用的函数,用于根据指定的条件返回一个向量或数组中满足条件的元素的位置。它的基本语法是: 其中: condition 是一个布尔数组或布尔条件表达式,用于指定需要满足的条件。 x 和 y 分别是满足条件和不满足条件时的替代值。它们可以是标量、

    2024年02月10日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包