MySql 组合索引的使用

news/2024/5/10 7:49:06

MySql 组合索引的使用

测试Mysql组合索引在不同的查询条件组合下的索引使用情况。当有a+b+c 3个字的的组合索引时,按照MySql 的左匹配原则,a+b+c,a+b,a 是满足左匹配原则,肯定是会走索引的,但是其他的场景,比如a+c, b+c, b+a, b+a+c 等是否仍会走索引呢?

测试环境

MySql 5.7

测试表:

CREATE TABLE `report_user_achievement` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',`user_id` int(11) NOT NULL COMMENT '用户id',`user_name` varchar(128) DEFAULT NULL COMMENT '用户名称',`is_inner` tinyint(1) NOT NULL COMMENT '是否为内部',`year` int(11) NOT NULL COMMENT '年',`month` int(11) NOT NULL COMMENT '月',`week_of_month` int(11) NOT NULL COMMENT '周(本月)',`date_time` datetime(6) NOT NULL COMMENT '日期',`achievement_amount` decimal(11,2) DEFAULT NULL COMMENT '业绩金额',`last_business_date_time` datetime(6) DEFAULT NULL COMMENT '最近的业务时间',PRIMARY KEY (`id`),KEY `idx__user_id__date_time__is_inner` (`user_id`,`date_time`,`is_inner`) COMMENT ''
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用户报表-业绩表'

测试

测试肯定走索引的场景

a+b+c,a+b,a

EXPLAIN
SELECT * FROM `report_user_expert_network_achievement` WHERE user_id = 56;  EXPLAIN
SELECT * FROM `report_user_expert_network_achievement` WHERE user_id = 56 AND date_time = '2023-12-07 00:00:00.000000';  EXPLAIN
SELECT * FROM `report_user_expert_network_achievement` WHERE user_id = 56 AND date_time = '2023-12-07 00:00:00.000000' AND is_inner = FALSE;  

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

EXPLAIN 结果三条记录都是走索引

测试肯定不走索引的场景

b, c, b+c,c+b

EXPLAIN
SELECT * FROM `report_user_achievement` WHERE date_time = '2023-12-07 00:00:00.000000' ; EXPLAIN
SELECT * FROM `report_user_achievement` WHERE is_inner = FALSE;  #ALL Using whereEXPLAIN
SELECT * FROM `report_user_achievement` WHERE date_time = '2023-12-07 00:00:00.000000' AND is_inner = FALSE; EXPLAIN
SELECT * FROM `report_user_achievement` WHERE is_inner = FALSE AND date_time = '2023-12-07 00:00:00.000000';

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

EXPLAIN 结果都是ALL 走了全表扫描,没有走索引。

测试可能会走索引的场景

由于Mysql 会对查询条件进行优化,即使没有按照索引的顺序的查询语句,也会按照索引进行优化。例如:b+a+c, b+c+a, c+a+b, c+b+a, b+a

EXPLAIN
SELECT * FROM `report_user_achievement` WHERE date_time = '2023-12-07 00:00:00.000000' AND user_id = 56 AND is_inner = FALSE; EXPLAIN
SELECT * FROM `report_user_achievement` WHERE date_time = '2023-12-07 00:00:00.000000' AND is_inner = FALSE AND user_id = 56 ; EXPLAIN
SELECT * FROM `report_user_achievement` WHERE is_inner = FALSE AND user_id = 56 AND date_time = '2023-12-07 00:00:00.000000'; EXPLAIN
SELECT * FROM `report_user_achievement` WHERE is_inner = FALSE AND date_time = '2023-12-07 00:00:00.000000' AND user_id = 56 ; EXPLAIN
SELECT * FROM `report_user_achievement` WHERE date_time = '2023-12-07 00:00:00.000000' AND user_id = 56; 

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

EXPLAIN 结果记录都是走索引,说明Where 语句中条件顺序不影响是否走索引。

测试索引下推

对于a+c,c+a 这组合,不完全满足左匹配,但又可以通过索引优化的组合。

EXPLAIN
SELECT * FROM `report_user_achievement` WHERE user_id = 56 AND is_inner = FALSE;  EXPLAIN
SELECT * FROM `report_user_achievement` WHERE is_inner = FALSE AND user_id = 56; 

在这里插入图片描述
在这里插入图片描述

测试结果是仍然走了索引,但和完全走索引不同的是Extra 字段多了Using index condition
原因是索引下推 这个MySql 5.7 正式完全支持的功能,

这是一段GPT 对索引下推的描述:

MySQL的索引下推(Index Condition Pushdown,简称ICP)是一个优化查询执行的特性,它允许MySQL在查询过程中更高效地利用复合索引。在没有索引下推的情况下,MySQL会根据索引快速定位到满足条件的记录,然后再回表读取完整的行数据,接着在服务器层面对这些数据进行条件过滤。
索引下推优化则是在获取索引的同时,将那些可以由索引中的列来评估的过滤条件推送到存储引擎层。这样,存储引擎在利用索引查找记录的同时,就可以对索引中的列进行条件过滤,只有满足条件的记录才会被读取并返回给服务器层。这样可以减少不必要的回表操作和数据传输,从而提高查询的效率。
索引下推适用于以下情况:

  • 查询使用了复合索引。
  • 查询条件中包含了索引列的部分或全部列的条件。
  • 存储引擎支持索引下推(InnoDB和MyISAM支持,而Memory存储引擎不支持)。

总结就是因为a+c 这个条件是可以在索引上直接进行过滤的,因此可以先通过索引过滤,再去回表去数据,从而提高效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.cpky.cn/p/10270.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

idea远程服务器debug

前提 本地代码和服务器代码一致 idea中创建远程服务 一般只需要修改ip,注意这边的端口是监听Socket的端口,不是服务的端口 然后把运行参数复制一下 -agentlib:jdwptransportdt_socket,servery,suspendn,address5005 tomcat启动 在tomcat的lib下的c…

JavaWeb - 3 - JavaScript(JS)

JavaScript(JS)官方参考文档:JavaScript 教程 JavaScript(简称:JS)是一门跨平台、面向对象的脚本语言,是用来控制网页行为的,它能使网页可交互(脚本语言就不需要编译,直接通过浏览器…

DataGrip 连接 Centos MySql失败

首先检查Mysql是否运行: systemctl status mysqld , 如果显示没有启动则需要启动mysql 检查防火墙是否打开,是否打开3306的端口 sudo firewall-cmd --list-all 如果下面3306没有打开则打开3306端口 publictarget: defaulticmp-block-inver…

2024届 C++ 刷题 笔试强训 Day 01

选择题 01 以下for循环的执行次数是&#xff08;&#xff09; for(int x 0, y 0; (y 123) && (x < 4); x); A 是无限循环 B 循环次数不定 C 4次 D 3次 解题思路&#xff1a; 我们直接来看本道题中最关键的部分&#xff1a;(y 123) && (x < 4)。 (y…

0环PEB断链实现

截止到昨天那里我们的思路就清晰了&#xff0c;通过EPROCESS找到我们要隐藏的进程的ActiveProcessLinks&#xff0c;将双向链表的值修改&#xff0c;就可以将我们想要隐藏的这个进程的ActiveProcessLinks从双向链表中抹去的效果&#xff0c;这里的话如果在windbg里面直接使用ed…

【Proteus仿真】【51单片机】井盖安全检测装置设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用LCD1602液晶显示模块、WIFI模块、蜂鸣器、LED按键、ADC PCF8591、角度/可燃气检测传感器等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD16…