mysql索引失效的坑

news2024/10/2 3:31:26

目录

前言

博客文章分享

对索引字段做函数操作

隐式类型转换

隐式字符编码转换

原因分析

解决方法:


前言

在MySQL中,有时候会因为语句使用不当导致sql不走索引,从而使数据库的压力变大。本篇分享一下sql不走索引的坑,让大家也避避坑!

博客文章分享

MySQL索引失效的场景

对索引字段做函数操作

DROP TABLE IF EXISTS `t_file`;
CREATE TABLE `t_file`  (
  `id` int(20) NOT NULL COMMENT '主键',
  `fileid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文件ID',
  `filename` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文件名',
  `sort` int(11) NOT NULL COMMENT '排序',
  `createtime` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `fileid`(`fileid`) USING BTREE,
  INDEX `createtime`(`createtime`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (11111, '1', '涨了', 1, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (22222, '2', 'aaaa', 2, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (33333, '21', 'asdq', 3, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (44444, '22', 'qweqwe', 4, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (55555, '23', 'wqes', 5, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (66666, '24', 'iuoty', 6, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (77777, '25', 'orooo', 7, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (88888, '26', 'asdq2', 8, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (99999, '27', '哇哦erqwr', 9, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (101010, '12', 'drfsrfe', 10, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (111111, '26', 'jkhd', 11, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (222222, '29', 'ghdwe2', 12, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (333333, '28', '规划局tu', 13, '2023-04-19 16:02:04');
INSERT INTO `high`.`t_file` (`id`, `fileid`, `filename`, `sort`, `createtime`) VALUES (444444, '24', 'sdrt3', 14, '2023-04-19 16:02:04');

假如有这么一个文件表,需求查询统计某个月份的文件。

EXPLAIN SELECT COUNT(*) FROM `t_file` where MONTH(createtime) = 4;

 结果:

        从结果看,Extra 字段的 Using index,表示的是使用了覆盖索引。     

        首先B+ 树提供的快速定位能力,来源于同一层兄弟节点的有序性。对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能。但不是说MySQL优化器不走createtime索引了,只是放弃了树搜索功能,优化器可以选择遍历主键索引或者索引 createtime,优化器对比索引大小后发现,索引 createtime更小,遍历这个索引比遍历主键索引来得更快。因此最终还是会选择索引 createtime。

        如果想使用上mysql的快速树搜索功能可以将sql改成下面这样的sql,但是这个sql的话每当有一年的数据就得加一行条件。

EXPLAIN SELECT COUNT(*) FROM `t_file` where 
(createtime>=2023-04-01 AND createtime<2023-05-01)
or (createtime>=2022-04-01 AND createtime<2022-05-01);

 建议不要在sql中对索引字段进行函数操作

隐式类型转换

还是使用t_file这个表,查询fileid等于22,索引字段是String但是输入是整形Int

EXPLAIN SELECT * FROM `t_file` where fileid = 22;

结果:

        从结果可以看出没有走索引,全表扫描了。

        规则:在 MySQL 中,字符串和数字做比较时,是将字符串转换成数字。

        所以sql语句在优化器中相当于下面这个sql

EXPLAIN SELECT * FROM `t_file` where CAST(fileid AS signed int) = 22;

 触发条件对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能。

        那么如果索引字段是int类型,但是输入的参数是string呢?

        因为MySQL的规则字符串和数字做比较时,是将字符串转换成数字,所以会走索引不会全表扫描。

隐式字符编码转换

       原因分析

        首先创建一个CHARACTER SET = utf8的表

DROP TABLE IF EXISTS `file_detail`;
CREATE TABLE `file_detail`  (
  `id` int(11) NOT NULL COMMENT 'id',
  `fileid` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件ID',
  `fileaddress` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件路径',
  `user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '上传用户',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `fileid`(`fileid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `high`.`file_detail` (`id`, `fileid`, `fileaddress`, `user`) VALUES (1, '1', 'c:/conf', '张三');
INSERT INTO `high`.`file_detail` (`id`, `fileid`, `fileaddress`, `user`) VALUES (2, '21', 'c:/config', '李四');
INSERT INTO `high`.`file_detail` (`id`, `fileid`, `fileaddress`, `user`) VALUES (3, '2', 'd:/high', 'wangwu');

 然后查询一下t_file与file_detail中fileid=21的信息,sql如下:

EXPLAIN SELECT fd.* FROM t_file tf,`file_detail` fd where  tf.fileid=fd.fileid and tf.id= 33333

结果:

        从结果上看sql执行顺序是:首先使用了主键索引从t_file取出ID为33333的这一行数据,然后从这行数据中取到fileid的值,最后用fileid的值去file_detail去做匹配。

        问题:file_detail表中fileid设置了索引,但是EXPLAIN结果确没有使用到?

        百度结果是:t_file使用的utf8mb4编码,file_detail使用的utf8编码,表连接查询时用不上关键字段的索引。划重点:字符集 utf8mb4 是 utf8 的超集,所以当这两个类型的字符串在做比较的时候,MySQL 内部的操作是,先把 utf8 字符串转成 utf8mb4 字符集,再做比较。

 MySQL 内部的操作相当于如下sql:

EXPLAIN SELECT * FROM file_detail WHERE CONVERT(fileid USING utf8mb4) = 21

        所以说最后用fileid的值去file_detail去做匹配时,连接过程中对索引字段做了函数操作,导致没有用上fileid索引。

知识点: CONVERT(expr USING transcoding_name) 函数是字符串转成 utf8mb4字符集。

 解决方法:

        1、将表的字符集改变成一致的utf8mb4(生产中不建议该操作)

        ALTER TABLE `high`.`file_detail` CHARACTER SET = utf8mb4;

        2、 不能修改字符集 ,麻烦点修改sql

EXPLAIN SELECT fd.* FROM t_file tf,`file_detail` fd where  fd.fileid=CONVERT(tf.fileid USING utf8) and tf.id= 33333

总结:

 写sql时多EXPLAIN一下,不要在sql中对索引字段进行函数操作,索引字段的参数可以用函数。

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

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

相关文章

Nginx 和Rewrite

系列文章目录 文章目录 系列文章目录一、常规的nginx正则表达式1.location和rewrite的区别2.常用的nginx的正则表达式3.nginx里面的优先级 二、rewrite1.Rewrite2.实验 总结 一、常规的nginx正则表达式 1.location和rewrite的区别 从功能看 rewrite 和 location 似乎有点像&a…

GPT-2隐私泄露论文阅读:Extracting Training Data from Large Language Models

文章目录 论文地址:原文阐释&#xff1a;渔樵问对&#xff1a;原理梗概预防策略隐私策略这个新颖的攻击方式是什么&#xff1f;三种典型采样策略&#xff1a;隐私风险文章第5页第二段中提到的 memorized training exam ple 是什么意思 ThreatModel &Ethics什么是文本的zlib…

【Apache 网页与安全优化】

1.网页压缩 检查是否安装 mod_deflate 模块 apachectl -t -D DUMP_MODULES | grep "deflate"如果没有安装mod_deflate 模块&#xff0c;重新编译安装 Apache 添加 mod_deflate 模块 systemctl stop httpd.service cd /usr/local/httpd/conf mv httpd.conf httpd.c…

数字硬件建模SystemVerilog-通信总线建模 --Interface端口的概念

来到了SV最后一部分&#xff0c;预计三篇文章&#xff0c;两周更完&#xff0c;所有的思维导图如下&#xff1a; 概述 SystemVerilog Interface是modport的一种&#xff0c;但比简单的输入、输出或输入输出端口的功能更多。在其最简单的形式中&#xff0c;Interface端口将相关的…

关于户外旋转LED显示屏的核心技术

户外旋转LED显示屏因可视范围达360的新颖结构&#xff0c;并且成本低廉&#xff0c;而得到了迅速的发展。虽然看着外观与普通LED显示屏没有什么大的异样&#xff0c;但为使设计的户外旋转LED显示屏具有较好的显示效果&#xff0c;背后也是需要通过众多工程技术人员克服技术难点…

git lfs简易使用教程

参考资料&#xff1a; https://zzz.buzz/zh/2016/04/19/the-guide-to-git-lfs/ 这篇随笔简单记录一下git lfs的使用教程&#xff0c;只记录最为常用的部分&#xff0c;并阐述原理&#xff0c;方便后面查阅。 首先说明一下git lfs的原理&#xff0c;看名称&#xff1a;git lfs。…

电力监控系统在智能建筑电气节能中的应用

摘要&#xff1a;电力监控系统在智能建筑中被广泛使用&#xff0c;其以及时、稳定、安全、便捷的优点提高了电能使用效率&#xff0c;节约了成本。借助电力监控系统能准确判断故障发生原因和位置&#xff0c;为智能建筑的安全性和智能化发展提供了有力的支持 关键词&#xff1…

华为,找寻科技秋天里的春光

捷克导演伏拉基米尔米切尔在2001年指导了一部电影&#xff0c;叫做《秋天里的春光 Bab lto》。 我很喜欢这个名字&#xff0c;它吐露着一种简单质朴的美好。回望历史&#xff0c;我们会发现文明与知识经常陷入秋天&#xff0c;但却因为人类的一次次努力&#xff0c;最终我们迎来…

电脑提示vcruntime140_1.dll丢失的正确修复方法

vcruntime140_1.dll是vs2010编译的程序默认的库文件它的丢失易导致游戏、应用软件等程序运行出现错误&#xff0c;致使程序无法正常运行&#xff0c;下面小编教大家电脑提示vcruntime140_1.dll丢失的正确修复教程 首先打开一个360&#xff0c;搜狗等等电脑浏览器&#xff0c;输…

ProxySQL技术实践分享

一、ProxySQL基本介绍 1.1 前言 ProxySQL是 MySQL 的高性能、高可用性、协议感知代理。以下为结合主从复制对ProxySQL读写分离、黑白名单、路由规则等做些基本测试。 1.2 基本介绍 先简单介绍下ProxySQL及其功能和配置&#xff0c;主要包括&#xff1a; 最基本的读/写分离&…

扬帆优配|北海道拉响警报!市场惊现500亿超级空单,有何大事?

又见超级大空单&#xff01; 据英国《金融时报》周三援引其剖析过的监管文件报导称&#xff0c;日本软银集团已开端出售其在阿里巴巴&#xff08;9988.HK&#xff09;简直一切剩下股份。陈述弥补说&#xff0c;这家由亿万富翁孙正义为创始人领导的日本集团本年经过预付远期合约…

PNAS: 这些病毒是原生动物基因组中的偷渡者

在对复杂单细胞微生物进行大规模研究时&#xff0c;奥地利因斯布鲁克大学生态学系的Christopher Bellas博士、Marie-Sophie Plakolb和Ruben Sommaruga教授发现了一个意外情况&#xff1a;微生物的基因组中找到超过30,000种先前未知的病毒DNA。这种“隐藏”的DNA可能允许宿主细胞…

5 种主流API网关技术选型,yyds

API网关是微服务项目的重要组成部分&#xff0c;今天来聊聊API网关的技术选型&#xff0c;有理论&#xff0c;有实战。 不 BB&#xff0c;上文章目录&#xff1a; 1 API网关基础 1.1 什么是API网关 API网关是一个服务器&#xff0c;是系统的唯一入口。 从面向对象设计的角…

Dubbo泛化调用返回结果对象参数丢失的问题分析

最近在使用jvm-sandbox-repeater做引流回放&#xff0c;针对dubbo的流量做相应的回放&#xff0c;结果发现一个问题dubbo接口录制的返回值与回放的返回值不一样。 问题排查 我们先看看返回的差异在什么地方 左侧是回放的流量返回结果&#xff0c; 右侧是录制的返回结果。 结果…

7款神仙级非常漂亮的 Linux 操作系统UI,你都用过吗

Linux 的发行版有很多&#xff0c;这里罗列7个漂亮的 Linux 发行版&#xff0c;可以说是Linux操作系统界的颜值担当了。 1、elementary OS 网站&#xff1a;https://elementaryos.cn elementary OS操作系统是最漂亮的Linux发行版之一。它基于macOS外观&#xff0c;同时为Linu…

裸机和RTOS系统区别与联系

1. 裸机和rtos的多任务处理 试想一种场景&#xff0c;我们正在打游戏&#xff0c;但女朋友在你打游戏的过程中给你发送消息&#xff0c;你需要回复消息 1.1 裸机处理方式 while(1) { 打游戏();回复信息(); }玩过51或者stm32的裸机编程的人都知道&#xff0c;我们往往会在应…

【MATLAB图像处理实用案例详解(11)】——基于Hough变换的人眼虹膜定位方法

目录 一、Hough变换基本原理二、算法流程2.1 分离瞳孔并估算虹膜内半径2.2 Hough变换定位内外虹膜 三、效果演示 一、Hough变换基本原理 Hough 变换作为一种参数空间变换算法&#xff0c;直线和其他参数化形状检测的重要工具。Hough 变换具有较强的稳定性和鲁棒性&#xff0c;…

【AI绘画】外网一直进不去?别担心,还有AI绘画小程序和文心一格

这是加入新星计划的最后一周的最后一篇文章啦&#xff01;文章的最后是我想总结一下从三月底到四月中旬这几十天的感想&#xff5e; 系列文章&#xff1a; 【AutoGPT】你自己运行&#xff0c;我先睡了—— ChatGPT过时了吗&#xff1f;_山楂山楂丸的博客-CSDN博客 目录 前言 …

pytest.mark

目录 一、Pytest简介 二、安装 三、pytest.mark 1.标记 2.参数化 3. skip跳过 4. xfail 该用例置为失败 一、Pytest简介 Pytest是python一个第三方测试框架&#xff0c;有非富的第三方插件可以扩展 特点&#xff1a; 简单灵活&#xff0c;容易上⼿&#xff1b;⽀持参数…

ASEMI代理ADM202EARNZ-REEL原装ADI车规级ADM202EARNZ-REEL

编辑&#xff1a;ll ASEMI代理ADM202EARNZ-REEL原装ADI车规级ADM202EARNZ-REEL 型号&#xff1a;ADM202EARNZ-REEL 品牌&#xff1a;ADI/亚德诺 封装&#xff1a;SOIC-16 批号&#xff1a;2023 引脚数量&#xff1a;16 安装类型&#xff1a;表面贴装型 ADM202EARNZ-REE…