【MySQL】MySQL不走索引的情况分析

未建立索引

当数据表没有设计相关索引时,查询会扫描全表。

create table test_temp
(test_id     int auto_incrementprimary key,field_1     varchar(20) null,field_2     varchar(20) null,field_3     bigint      null,create_date date        null
);
explain 
select * from test_temp where field_1 = 'testing0';

在这里插入图片描述

建议

查询频繁是数据表字段增加合适的索引。

查询结果集是原表中的大部分数据

当数据库查询命中索引时,数据库会首先利用索引列的值定位到对应的数据节点。这个数据节点上记录了对应数据行的行标识符(Row Identifier)。然而,如果查询需要获取该行其他列的数据,就需要进行回表操作。

在回表操作中,数据库会使用行标识符再次访问数据节点或磁盘上的实际数据行,以获取完整的数据。这个过程被称为回表。回表操作可能会增加额外的磁盘访问和数据检索的开销,因此,在某些情况下,当MySQL判断回表所需的资源大于直接扫描全表时,它可能选择不走索引,而是执行全表扫描。
在这里插入图片描述

建议

  1. 索引覆盖:酌情考虑创建包含查询所需列的索引,查询结果集全部被索引覆盖,无需回表。
  2. 调整查询语句:查询必要的列、使用Join语句优化查询语句,减少回表次数。
  3. 当表数据量较大时,需考虑其他存储服务。

使用函数、隐式转换

使用函数

在这里插入图片描述

在这里插入图片描述

隐式转换

数据准备:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for products
-- ----------------------------
DROP TABLE IF EXISTS `products`;
CREATE TABLE `products` (`id` int NOT NULL,`name` varchar(255) NOT NULL,`price` decimal(10,2) NOT NULL,`description` text,`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`type` tinyint NOT NULL COMMENT '商品类型',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;-- ----------------------------
-- Records of products
-- ----------------------------
BEGIN;
INSERT INTO `products` VALUES (1, 'Product A', 10.99, 'This is the description for Product A', '2023-08-11 03:47:06', '2023-08-11 03:49:24', 1);
INSERT INTO `products` VALUES (2, 'Product B', 19.99, 'This is the description for Product B', '2023-08-11 03:47:07', '2023-08-11 03:49:24', 2);
INSERT INTO `products` VALUES (3, 'Product C', 5.99, 'This is the description for Product C', '2023-08-11 03:47:07', '2023-08-11 03:49:25', 3);
INSERT INTO `products` VALUES (4, 'Product D', 8.49, 'This is the description for Product D', '2023-08-11 03:47:07', '2023-08-11 03:49:24', 2);
INSERT INTO `products` VALUES (5, 'Product E', 15.99, 'This is the description for Product E', '2023-08-11 03:47:07', '2023-08-11 03:49:25', 2);
INSERT INTO `products` VALUES (6, 'Product F', 12.99, 'This is the description for Product F', '2023-08-11 03:47:08', '2023-08-11 03:49:24', 2);
INSERT INTO `products` VALUES (7, 'Product G', 7.99, 'This is the description for Product G', '2023-08-11 03:47:08', '2023-08-11 03:49:24', 2);
INSERT INTO `products` VALUES (8, 'Product H', 9.99, 'This is the description for Product H', '2023-08-11 03:47:08', '2023-08-11 03:49:24', 2);
INSERT INTO `products` VALUES (9, 'Product I', 14.99, 'This is the description for Product I', '2023-08-11 03:47:09', '2023-08-11 03:49:24', 2);
INSERT INTO `products` VALUES (10, 'Product J', 11.99, 'This is the description for Product J', '2023-08-11 03:47:09', '2023-08-11 03:49:24', 2);
COMMIT;SET FOREIGN_KEY_CHECKS = 1;

增加索引

ALTER TABLE products
ADD INDEX idx_type (type);

复现:

explain
select * from products where type in ('1','2');

由于type是tinyint类型,因此,以上SQL等效为:

SELECT * FROM products WHERE type in CAST('1' AS tinyint,'2' as tinyint);

在这里插入图片描述

由于使用了CAST()函数,会导致不走索引的现象。
还有一种情况是:在关联查询时,驱动表关联字段两者排序规则不一致时也会导致不走索引。

in/not in <>条件导致不走索引

in、not in、<>不走索引的原因是相似的,以下基于in语句分析。
in条件导致不走索引的情况:

in条件过多

explain
select * from products where type in (1,2,3,4,5,6,7);

如果 IN 条件中包含太多的值,超出了数据库管理系统的限制,它可能会选择不使用索引。

建议

当in条件中的数据是连续时,可以使用between and代替in。
分而治之,将一次查询分为多次查询,最后取并集。
使用UNION语句,类似方案一,只不过该方案是在SQL层面完成。

SELECT column1, column2, ...
FROM your_table
WHERE column IN (value1, value2, ..., valueN)
UNION
SELECT column1, column2, ...
FROM your_table
WHERE column IN (valueN+1, valueN+2, ..., valueM)

统计信息不准确

SHOW ENGINE INNODB STATUS;

该命令会查询出MySQL Inndb存储引擎的操作情况,信息包含Innodb各种统计信息:

  • Inserts:已插入的行数。
  • Updates:已更新的行数。
  • Deletes:已删除的行数。
  • Reads:已读取的行数。

innodb表的统计信息并不是实时统计更新,如果统计信息和实际的索引信息差异很大,就会导致优化器计算各个索引成本后,做出非预期的选择。出现这种现象的场景是:当有大量数据在短时间内落库时,Innodb还没更新统计相关信息,此时来了一个查询,MySQL会基于历史数据做出错误的判断:当前表数据量少,不走索引更高效。

建议

基于此问题的解决方案是:手动更新相关统计数据。
请参考:
www.modb.pro/db/46678

like语句

like语句无法命中索引的情况:

前导通配符:%value
通配符在字符串的中间:value%value
通配符"_"出现在开头

建议

尽量避免在模式的开头使用前导通配符 %
如果无法避免第一种,根据实际业务和查询语句考虑使用后缀索引
将通配符 % 放在模式的末尾,以便进行前缀匹配。
如果需要在模式的中间使用通配符 %,可以考虑使用全文搜索引擎或其他更适合模式匹配的技术。
对于固定长度的模式匹配,可以考虑使用其他操作符,如 = 或 <>

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

好用的免费音频转换器大揭秘

你是否曾经遇到过这样的情况&#xff1a;你有一首喜欢的歌曲或者音频文件&#xff0c;但是你的播放器或设备不支持该文件格式&#xff1f;这时候&#xff0c;你需要一款好用的音频格式转换器来帮助你。说到这&#xff0c;你可能会问&#xff0c;“我都不知道免费的音频格式转换…

案例15 Spring Boot入门案例

1. 选择Spring Initializr快速构建项目 ​ 2. 设置项目信息 ​ 3. 选择依赖 ​ 4. 设置项目名称 ​ 5. 项目结构 ​ 6. 项目依赖 自动配置了Spring MVC、内置了Tomcat、配置了Logback(日志)、配置了JSON。 ​ 7. 创建HelloController类 com.wfit.boot.hello目录下创建HelloCo…

博客网站添加复制转载提醒弹窗Html代码

网站如果是完全禁止右键&#xff08;复制、另存为等&#xff09;操作&#xff0c;对用户来说体验感会降低&#xff0c;但是又不希望自己的原创内容直接被copy&#xff0c;今天飞飞和你们分享几行复制转载提醒弹窗Html代码。 效果展示&#xff1a; 复制以下代码&#xff0c;将其…

聚观早报 | 近2亿“救命款”每日优鲜不卖菜了;小鹏G6难过交付关

【聚观365】8月14日消息 近2亿元“救命款”每日优鲜不卖菜了 小鹏爆款G6难过交付关 AIGC在数字营销领域应用程度 iPhone SE 4设计基于iPhone 14 Modulal寻求A轮融资挑战英伟达 近2亿元“救命款”每日优鲜不卖菜了 从一家基于前置仓模式的蔬菜水果等本地生活服务商&#x…

verilog 实现异步fifo

理论知识参考 异步FIFO_Verilog实现_verilog实现异步fifo_Crazzy_M的博客-CSDN博客 代码 /* 位宽8bit, 位深8 */ module async_fifo#(parameter FIFO_DEPTH 8,parameter FIFO_WIDTH 8 ) (input rst_n,input wr_clk,input wr_en,input [FIFO_WIDTH - 1:0…

docker通用镜像方法,程序更新时不用重新构建镜像

docker通用镜像方法&#xff0c;程序更新时不用重新构建镜像。更新可执行文件后&#xff0c;重新启动容器就可运行。 功能 1、在demo目录下添加脚本文件start.sh&#xff0c;里面执行demo.jar文件。 2、将demo目录映射到镜像下的 /workspace目录。 3、Dockerfile文件中默认…

自动化更新导致的各种问题解决办法

由于最近自动化频频更新导致出现各种问题&#xff0c;因此在创建驱动对象代码时改成这种方式 我最近就遇到了由于更新而导致的代码报错&#xff0c;报错信息如下&#xff1a; 复制内容如下&#xff1a; Exception in thread “main” org.openqa.selenium.remote.http.Connecti…

JVM笔记 —— 出现内存溢出错误时时如何排查

一、出现内存溢出的几种情况 内存溢出错误分为StackOverflowError和OutOfMemoryError&#xff0c;前者是栈中出现溢出&#xff0c;后者一般是堆或方法区出现溢出&#xff0c;简称OOM 1. 栈溢出 StackOverflowError 栈溢出一般都是因为没有正确的结束递归导致的&#xff0c;无…

大数据课程I1——Kafka的概述

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Kafka的概念; ⚪ 掌握Kafka的配置与启动; 一、简介 1. 基本概念 Apache kafka 是一个分布式数据流平台。可以从如下几个层面来理解: 1. 我们可以向Kafka发布数据以及从Kafka订阅…

ARM--day2(cpsr、spsr、数据搬移指令、移位操作指令、位运算操作指令、算数运算指令、比较指令、跳转指令)

.text .global _gcd _gcd:mov r0,#9mov r1,#15b loop loop:cmp r0,r1beq stopsubhi r0,r1bhi loopsubcc r1,r0bcc loopstop:b stop.end用for循环实现1~100之间和5050 .text .global _gcd _gcd:mov r0,#0x0mov r1,#0x1mov r2,#0x64b loop loop:cmp r1,r2bhi stopadd r0,r0,r1ad…

Linux Day07

一、僵死进程 1.1僵死进程产生的原因 子进程先于父进程结束, 而父进程没有获取子进程退出码&#xff0c;释放子进程占用的资源&#xff0c;此时子进程将成为一个僵死进程。 在第一个框这里时父进程子进程都没有结束&#xff0c;显示其pid 父进程是2349&#xff0c;子进程是235…

MySQL高阶知识点(一)一条SQL【更新】语句是如何执行的

一条SQL【更新】语句是如何执行的 首先&#xff0c;可以确定的说&#xff0c;【查询】语句的那一套流程&#xff0c;【更新】语句也是同样会走一遍&#xff0c;与查询流程不一样的是&#xff0c; 更新语句涉及到【事务】&#xff0c;就必须保证事务的四大特性&#xff1a;ACID&…