【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.mzph.cn/news/37092.shtml

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

相关文章

ffmpeg命令行是如何打开vf_scale滤镜的

前言 在ffmpeg命令行中&#xff0c;ffmpeg -i test -pix_fmt rgb24 test.rgb&#xff0c;会自动打开ff_vf_scale滤镜&#xff0c;本章主要追踪这个流程。 通过gdb可以发现其基本调用栈如下&#xff1a; 可以看到&#xff0c;query_formats&#xff08;&#xff09;中创建的v…

maven install

maven install maven 的 install 命令&#xff0c;当我们的一个 maven 模块想要依赖其他目录下的模块时&#xff0c;直接添加会找不到对应的模块&#xff0c;只需要找到需要引入的模块&#xff0c;执行 install 命令&#xff0c;就会将该模块放入本地仓库&#xff0c;就可以进…

Vue3 setup tsx 子组件向父组件传值 emit

需求&#xff1a;Vue3 setup 父组件向子组件传值&#xff0c;子组件接收父组件传入的值&#xff1b;子组件向父组件传值&#xff0c;父组件接收的子组件传递的值。 父组件&#xff1a;parent.tsx&#xff1a; import { defineComponent, ref, reactive } from vue; import To…

Server - 文字转语音 (Text to Speech) 的在线服务 TTSMaker

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132287193 TTSMaker 是一款免费的文本转语音工具&#xff0c;提供语音合成服务&#xff0c;支持多种语言&#xff0c;包括英语、法语、德语、西班…

Exams/ece241 2013 q4

蓄水池问题 S3 S2 S1 例如&#xff1a;000 代表 无水 &#xff0c;需要使FR3, FR2, FR1 都打开&#xff08;111&#xff09; S3 S2 S1 FR3 FR2 FR1 000 111 001 011 011 001 111 000 fr代表水变深为…

快手商品详情数据API 抓取快手商品价格、销量、库存、sku信息

快手商品详情数据API是用来获取快手商品详情页数据的接口&#xff0c;请求参数为商品ID&#xff0c;这是每个商品唯一性的标识。返回参数有商品标题、商品标题、商品简介、价格、掌柜昵称、库存、宝贝链接、宝贝图片、商品SKU等。 接口名称&#xff1a;item_get 公共参数 名…

【PostgreSQL的CLOG解析】

同样还是这张图&#xff0c;之前发过shared_buffer和os cache、wal buffer和work mem的文章&#xff0c;今天的主题是图中的clog&#xff0c;即 commit log&#xff0c;PostgreSQL10之前放在数据库目录的pg_clog下面。PostgreSQL10之后修更名为xact,数据目录变更为pg_xact下面&…

WPF 本地化的最佳做法

WPF 本地化的最佳做法 资源文件英文资源文件 en-US.xaml中文资源文件 zh-CN.xaml 资源使用App.xaml主界面布局cs代码 App.config辅助类语言切换操作类资源 binding 解析类 实现效果 应用程序本地化有很多种方式&#xff0c;选择合适的才是最好的。这里只讨论一种方式&#xff0…

pytorch单机多卡后台运行

nohup sh ./train_chat.sh > train_chat20230814.log 2>1&参考资料 Pytorch单机多卡后台运行的解决办法

kafka-2.12使用记录

kafka-2.12使用记录 安装kafka 2.12版本 下载安装包 根据你的系统下载rpm /deb /zip包等等, 这里我使用的是rpm包 安装命令 rpm -ivh kafka-2.12-1.nfs.x86_64.rpm启动内置Zookeeper 以下命令要写在同一行上 /opt/kafka-2.12/bin/zookeeper-server-start.sh /opt/kafka-2…

实验二十八、三角波发生电路参数的确认

一、题目 利用 Multisim 确定图1所示电路中各元件的参数&#xff0c;使输出电压的频率为 500 Hz 500\,\textrm{Hz} 500Hz、幅值为 6 V 6\,\textrm{V} 6V 的三角波。 图 1 三角波发生电路 图1\,\,三角波发生电路 图1三角波发生电路 2、仿真电路 A 1 \textrm A_1 A1​ 采用…

sift-1M数据集的读取及ES插入数据

sift是检查ann近邻召回率的标准数据集,ann可以选择faiss,milvus等库或者方法;sift数据分为query和base,以及label(groundtruth)数据。本文采用sift-1M进行解读,且看如下: 1、sift-1m数据集 官方链接地址:Evaluation of Approximate nearest neighbors: large datase…

Java:简单算法:冒泡排序、选择排序、二分查找

冒泡排序 // 1、准备一个数组 int[] arr {5&#xff0c;2&#xff0c;3&#xff0c;1};//2、定义一个循环控制排几轮 for (int i 0; i < arr.length - 1; i) { // i 0 1 2 【5&#xff0c;2&#xff0c;3&#xff0c;1】 次数 // i 0 第一轮 0 1 2 …

「网络」网络安全必须知道的19个知识分享

一、防火墙&#xff08;Firewall&#xff09; 定义&#xff1a;都知道防火墙是干什么用的&#xff0c;但我觉得需要特别提醒一下&#xff0c;防火墙抵御的是外部的攻击&#xff0c;并不能对内部的病毒 ( 如ARP病毒 ) 或攻击没什么太大作用。 功能 : 防火墙的功能主要是两个网…

Vue2-收集表单数据、过滤器、内置指令与自定义指令、Vue生命周期

&#x1f954;&#xff1a;我徒越万重山 千帆过 万木自逢春 更多Vue知识请点击——Vue.js VUE2-Day4 收集表单数据1、不同标签的value属性2、v-model的三个修饰符 过滤器内置指令与自定义指令1、内置指令2、自定义指令定义语法&#xff08;1&#xff09;函数式&#xff08;2&am…

文献综述|NLP领域后门攻击、检测与防御

前言&#xff1a;在信息安全中后门攻击&#xff08;Backdoor Attack&#xff09;是指绕过安全控制而获取对程序或系统访问权的方法。而随着深度学习以及各种神经网络模型的广泛应用&#xff0c;神经网络中存在的后门问题也引起了研究人员的广泛关注。神经网络后门攻击就是使网络…

Android AOSP源码编译——AOSP整编(二)

切换到源码目录下执行下面命令 1、初始化环境 . build/envsetup.sh //清除缓存 make clobber2、选择编译目标 lunchAOSP 预制了很多 Product。这里为了简单我们先不用真机&#xff0c;而是选择模拟器的方式&#xff0c;对于 x86_64 模拟器&#xff0c;我们选择的是 aosp_x86…

深度学习笔记(kaggle课程《Intro to Deep Learning》)

一、什么是深度学习&#xff1f; 深度学习是一种机器学习方法&#xff0c;通过构建和训练深层神经网络来处理和理解数据。它模仿人脑神经系统的工作方式&#xff0c;通过多层次的神经网络结构来学习和提取数据的特征。深度学习在图像识别、语音识别、自然语言处理等领域取得了…

Opencv将数据保存到xml、yaml / 从xml、yaml读取数据

Opencv将数据保存到xml、yaml / 从xml、yaml读取数据 Opencv提供了读写xml、yaml的类实现&#xff1a; 本文重点参考&#xff1a;https://blog.csdn.net/cd_yourheart/article/details/122705776?spm1001.2014.3001.5506&#xff0c;并将给出文件读写的具体使用实例。 1. 官…

C++多线程场景中的变量提前释放导致栈内存异常

多线程场景中的栈内存异常 在子线程中尝试使用当前函数的资源&#xff0c;是非常危险的&#xff0c;但是C支持这么做。因此C这么做可能会造成栈内存异常。 正常代码 #include <iostream> #include <thread> #include <windows.h>// 线程函数&#xff0c;用…