当前位置: 首页 > news >正文

MySQL中使用函数会使索引失效?

文章目录

  • 1、前置准备
  • 2、ChatGPT的答案
  • 3、实践证明
    • SQL1
    • SQL2
    • SQL3
    • SQL4
    • SQL5
  • 4、总结

1、前置准备

首先创建我们要测试的库表

CREATE TABLE `lianhe_index` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',`name` varchar(255) DEFAULT NULL,`age` int(11) DEFAULT NULL,`number` int(11) DEFAULT NULL,`create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`),KEY `idx_nameagenumber` (`name`,`age`,`number`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=200001 DEFAULT CHARSET=utf8;

主要建立了主键索引id和联合索引idx_nameagenumber,造了10W条数据。
一般函数可以使用在select子句中的列,也可以使用在where子句中的列,下面我们就这两种情况来分析下。

2、ChatGPT的答案

首先我们来问下ChatGPT
在这里插入图片描述
在MySQL中,使用函数作为select字段通常不会走索引。这是因为函数的使用会导致MySQL无法直接匹配索引键值,而是需要对所有记录进行函数计算后才能确定结果。然而,某些特殊情况下,MySQL可能会通过某些优化策略来利用索引,例如在某些情况下可以使用覆盖索引来避免访问表数据。
对于where字段的情况,使用函数作为条件通常也不会走索引。同样的原因,函数的使用会导致MySQL无法直接匹配索引键值,而是需要对所有记录进行函数计算后才能确定结果。因此,如果希望where字段能够走索引,建议尽量避免使用函数。
上面是ChatGPT的回答,回答正确?先保留答案,接下来我们来实践下~

3、实践证明

我们主要分析下面这5条SQL,先猜猜看会不会走索引?

SELECT id,age,number,UPPER(name),create_time FROM lianhe_index where name='林伟' and age=69 and number=76291;
SELECT id,age,number,name,create_time FROM lianhe_index where UPPER(name)='伟A' and age=69 and number=76291;
SELECT id,age,number,name,create_time FROM lianhe_index where name=UPPER(name) and age=69 and number=76291;
SELECT id,age,number,name,create_time FROM lianhe_index where UPPER(name)='伟A' and age=69 and number=76291 and DATE(create_time)="2022-11-11";
SELECT id,age,number,name,create_time FROM lianhe_index where name=UPPER(name) and age=69 and number=76291 and DATE(create_time)="2022-11-11";

执行计划如下,和你想的一样?

mysql> EXPLAIN SELECT id,age,number,UPPER(name),create_time FROM lianhe_index where name='林伟' and age=69 and number=76291;
EXPLAIN SELECT id,age,number,name,create_time FROM lianhe_index where UPPER(name)='伟A' and age=69 and number=76291;
EXPLAIN SELECT id,age,number,name,create_time FROM lianhe_index where name=UPPER(name) and age=69 and number=76291;
EXPLAIN SELECT id,age,number,name,create_time FROM lianhe_index where UPPER(name)='伟A' and age=69 and number=76291 and DATE(create_time)="2022-11-11";
EXPLAIN SELECT id,age,number,name,create_time FROM lianhe_index where name=UPPER(name) and age=69 and number=76291 and DATE(create_time)="2022-11-11";
+----+-------------+--------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------+
| id | select_type | table        | partitions | type | possible_keys     | key               | key_len | ref               | rows | filtered | Extra |
+----+-------------+--------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------+
|  1 | SIMPLE      | lianhe_index | NULL       | ref  | idx_nameagenumber | idx_nameagenumber | 778     | const,const,const |    1 |   100.00 | NULL  |
+----+-------------+--------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------+
1 row in set (0.02 sec)+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table        | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | lianhe_index | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 99954 |     1.00 | Using where |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
1 row in set (0.02 sec)+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table        | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | lianhe_index | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 99954 |     0.10 | Using where |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
1 row in set (0.02 sec)+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table        | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | lianhe_index | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 99954 |     1.00 | Using where |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
1 row in set (0.02 sec)+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table        | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | lianhe_index | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 99954 |     0.10 | Using where |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
1 row in set (0.02 sec)

下面我们逐个来分析下

SQL1

SELECT id,age,number,UPPER(name),create_time FROM lianhe_index where name='林伟' and age=69 and number=76291;
+----+-------------+--------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------+
| id | select_type | table        | partitions | type | possible_keys     | key               | key_len | ref               | rows | filtered | Extra |
+----+-------------+--------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------+
|  1 | SIMPLE      | lianhe_index | NULL       | ref  | idx_nameagenumber | idx_nameagenumber | 778     | const,const,const |    1 |   100.00 | NULL  |
+----+-------------+--------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------+

可以看到,执行计划中的key是使用到了组合索引idx_nameagenumber,扫码的行数rows=1,所以,索引生效
虽然RIGHT(name,1)是一个函数,但是它是在where子句中应用于已经在索引中的列name上的,所以MySQL可以使用索引来定位匹配的行

如果我们不查询create_time,还会发现执行计划中Extra中出现了Using index,表示使用了覆盖索引

SELECT id,age,number,UPPER(name) FROM lianhe_index where name='林伟' and age=69 and number=76291;
+----+-------------+--------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------------+
| id | select_type | table        | partitions | type | possible_keys     | key               | key_len | ref               | rows | filtered | Extra       |
+----+-------------+--------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------------+
|  1 | SIMPLE      | lianhe_index | NULL       | ref  | idx_nameagenumber | idx_nameagenumber | 778     | const,const,const |    1 |   100.00 | Using index |
+----+-------------+--------------+------------+------+-------------------+-------------------+---------+-------------------+------+----------+-------------+

SQL2

SELECT id,age,number,name,create_time FROM lianhe_index where UPPER(name)='伟A' and age=69 and number=76291;
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table        | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | lianhe_index | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 99954 |     1.00 | Using where |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+

可以看到,执行计划中的key=null,rows=99954,Extra列显示为"Using where",这表示查询使用了where子句进行过滤,但没有使用索引

如果我们不查询create_time,可以发现在执行计划中,“possible_keys"列显示为"NULL”,这表示没有其他可用的索引。但是在"key"列中显示了"idx_nameagenumber",这表示该索引被选择用于执行查询。此外,Extra列显示了"Using where; Using index",这表示查询使用了where子句进行过滤,并且使用了索引来定位匹配的行。所以是使用了索引,但效果不佳,个人觉得执行计划这里是有问题的

SELECT id,age,number,name FROM lianhe_index where UPPER(name)='伟A' and age=69 and number=76291;
+----+-------------+--------------+------------+-------+---------------+-------------------+---------+------+-------+----------+--------------------------+
| id | select_type | table        | partitions | type  | possible_keys | key               | key_len | ref  | rows  | filtered | Extra                    |
+----+-------------+--------------+------------+-------+---------------+-------------------+---------+------+-------+----------+--------------------------+
|  1 | SIMPLE      | lianhe_index | NULL       | index | NULL          | idx_nameagenumber | 778     | NULL | 99954 |     1.00 | Using where; Using index |
+----+-------------+--------------+------------+-------+---------------+-------------------+---------+------+-------+----------+--------------------------+

SQL3

SELECT id,age,number,name,create_time FROM lianhe_index where name=UPPER(name) and age=69 and number=76291;
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table        | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | lianhe_index | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 99954 |     0.10 | Using where |

可以看到,执行计划中的key=null,rows=99954,Extra列显示为"Using where",这表示查询使用了where子句进行过滤,但没有使用索引

SQL4

SELECT id,age,number,name,create_time FROM lianhe_index where UPPER(name)='伟A' and age=69 and number=76291 and DATE(create_time)="2022-11-11";
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table        | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | lianhe_index | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 99954 |     1.00 | Using where |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+

可以看到,执行计划中的key=null,rows=99954,Extra列显示为"Using where",这表示查询使用了where子句进行过滤,但没有使用索引

SQL5

SELECT id,age,number,name,create_time FROM lianhe_index where name=UPPER(name) and age=69 and number=76291 and DATE(create_time)="2022-11-11";
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table        | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+--------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | lianhe_index | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 99954 |     0.10 | Using where |

可以看到,执行计划中的key=null,rows=99954,Extra列显示为"Using where",这表示查询使用了where子句进行过滤,但没有使用索引

4、总结

当函数应用于select子句中的索引列时,索引仍然生效;当函数应用于where子句中的索引列时,MySQL可能无法使用索引来加快查询速度,虽然存在部分情况,执行计划显示keys使用了索引,但实际效果不佳,可以当作索引失效了。

相关文章:

MySQL中使用函数会使索引失效?

文章目录 1、前置准备2、ChatGPT的答案3、实践证明SQL1SQL2SQL3SQL4SQL5 4、总结 1、前置准备 首先创建我们要测试的库表 CREATE TABLE lianhe_index (id int(11) NOT NULL AUTO_INCREMENT COMMENT id,name varchar(255) DEFAULT NULL,age int(11) DEFAULT NULL,number int(1…...

金和OA C6任意文件读取漏洞 复现[附POC]

文章目录 金和OA C6任意文件读取漏洞 复现[附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 金和OA C6任意文件读取漏洞 复现[附POC] 0x01 前言 免责声明:请勿利用文章内的相关技术从事非法测试…...

IP地址技术原理

IP地址是互联网中的关键元素,它允许数据在全球范围内进行路由和传输。本文将深入探讨IP地址的技术原理,包括IP地址的结构、IP地址分配、子网划分和IPv4与IPv6之间的转换。 第一部分:IP地址基础 1.1IP地址是什么? IP地址&#xf…...

【网络安全】密码学基础

前言 密码学是网络安全的核心组成部分,它帮助我们保护信息,防止未经授权的访问。在这篇文章中,我们将从基础开始,深入了解密码学的基本概念和原理,包括加密、解密、密钥、哈希函数等。我们将尽可能使用简单的语言和实…...

AWS AD Connector 的网络配置

配置 AWS 的 AD Connector 通常遇到的都是些网络问题,且 AD Connector 本身屏蔽了一些网络细节,使得查找root cause往往有点困难,本文就把 AD Connector 网络问题梳理一下。 首先,需要搞清楚的是:AD Connector 是 Microsoft Active Directory 的一种代理,IAM可以通过它联…...

kafka详解(三)

2.2 Kafka命令行操作 2.2.1 主题命令行操作 1)查看操作主题命令参数 [aahadoop102 kafka]$ bin/kafka-topics.sh2)查看当前服务器中的所有topic (配置了环境变量不需要写bin/) [aahadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server hadoop10…...

[Spring] SpringMVC 简介(二)

目录 五、域对象共享数据 1、使用 ServletAPI 向 request 域对象共享数据 2、使用 ModelAndView 向 request 域对象共享数据 3、使用 Model、Map、ModelMap 向 request 域对象共享数据 4、向 session 域和 application 域共享数据 六、SpringMVC 的视图 1、ThymeleafVie…...

idea一些不太常用但是能提升编码效率的快捷键

Ctrl Shift V:从历史选择粘贴 从历史剪粘版中选择要粘贴的内容。Ctrl Shift Z:重做 恢复上一步撤销内容Shift F4:在新窗口中打开 比如要从另一个类中复制代码 可以把这个类在新窗口单独打开 用AltTab 来回切换复制Ctrl PageUp&#xff…...

vsto word属性信息 并读取

要通过VSTO (Visual Studio Tools for Office) 读取和操作 Microsoft Word 文档的属性信息,您可以使用 C# 或 VB.NET 等 .NET 编程语言结合 VSTO 来实现。以下是一个示例,演示如何获取 Word 文档的属性信息:首先,确保您已经在 Vis…...

android之TextView自由选择复制

文章目录 前言一、效果图二、实现步骤1.OnSelectListener2.SelectionInfo类3.TextLayoutUtil类4.复制弹框的xml布局5.弹框背景Drawable6.倒三角Drawable7.复制工具类8.调用 总结 前言 根据时代进步,那些干产品的也叼砖起来了,今天就遇到一个需求&#x…...

【mysql】 bash: mysql: command not found

在linux 服务器上安装了mysql 也可以正常运行。 但是执行命令,系统提示:bash: mysql: command not found bash:mysql:找不到命令 执行的命令是: mysql -u root -h 127.0.0.1 -p由于系统默认会查找的 /usr/bin/ 中下的命令,如…...

鲲山科技:引入和鲸 ModelWhale,实现量化策略的高效迭代

量化投资是数据科学在金融行业的应用。 2023 年,量化行业的超额收益开始收敛,量化私募如何形成自身核心竞争力? 和鲸拜访客户鲲山科技(深圳),揭示其“弯道超车”的独家秘诀。 群体作战 年初至今&#xff…...

PFSK152 3BSE018877R1 有源滤波器的定义

PFSK152 3BSE018877R1 有源滤波器的定义 有源滤波器是以晶体管和运算放大器为基本元件设计的滤波电路。除了这些元件,有源滤波器的电路还包含电阻和电容,但不包含电感。 我们知道滤波器具有频率选择性。因此,有源滤波器电路使用晶体管和运算…...

WebDAV之π-Disk派盘 + 恒星播放器

想要拥有一款万能视频播放器,全能解码播放器,无需转码,支持所有格式的视频和音频,直接播放的播放器?那就选恒星播放器。 恒星播放器支持视频投屏,倍速播放,后台播放等功能,还能一键截图和录制gif动图。支持全格式超高清真4K解码,蓝光HDR低占用,支持ISO文件直出的播放…...

亚马逊,速卖通,敦煌产品测评补单攻略:低成本、高安全实操指南

随着电商平台的发展和消费者对产品质量的要求提升,测评补单成为了商家们提升销售和用户口碑的关键环节。然而,如何在保持成本低廉的同时确保操作安全,一直是卖家们面临的挑战。今天林哥分享一些实用的技巧和策略,帮助卖家们产品的…...

常用linux解压命令

1. 超过4g的zip文件在linux下unzip失败。需要用7z压缩,然后用p7zip命令解压。 p7zip -d x.7z 2. gzip解压.gz文件 gzip -d a11.txt.gz 和 gunzip a1.txt.gz gunzip –c filename.gz > filename #解压缩保留源文件, 上述命令非常容易写错,最后导…...

TensorFlow入门(二十二、梯度下降)

梯度下降的定义及作用 梯度下降本身是一个最优化算法,通常也被称为最速下降法。常被用于机器学习和人工智能中递归性地逼近最小偏差模型,也就是使用它找到一个函数的局部极小值。 使用过程中,梯度下降算法以函数上当前点对于梯度(或者是近似梯度)反方向的规定步长距离点进行迭代…...

WPF中的多重绑定

MultiBinding 将会给后端传回一个数组, 其顺序为绑定的顺序. 例如: <DataGridMargin"10"AutoGenerateColumns"False"ItemsSource"{Binding Stu}"><DataGrid.Columns><DataGridTextColumn Binding"{Binding Id}" Header…...

区块链在游戏行业的应用

区块链技术在游戏行业有许多潜在的应用&#xff0c;它可以改变游戏开发、发行和玩家交互的方式。以下是区块链技术在游戏行业的一些主要应用&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.游戏资产…...

uniapp快速入门系列(4)- 微信小程序开发

第四章 微信小程序开发 4.1 微信小程序开发与uniapp的融合4.2 微信小程序API在uniapp中的使用4.3 微信小程序常见问题的解决方法问题1: 如何获取用户信息&#xff1f;问题2: 如何获取当前位置&#xff1f;问题3: 如何发送网络请求&#xff1f; 在本章中&#xff0c;我们将学习如…...

机器人双目视觉定位系统设计与开发

机器人双目视觉定位系统设计与开发 摘要 双目视觉定位技术是机器人感知环境、实现自主导航和精准操作的核心技术之一。本系统基于双目立体视觉原理,利用Matlab平台完成了从相机标定、图像采集、立体匹配到三维坐标解算的完整流程。系统采用张正友标定法获取相机内外参数,通…...

3步实现跨系统文件互通:WinBtrfs驱动全解析

3步实现跨系统文件互通&#xff1a;WinBtrfs驱动全解析 【免费下载链接】btrfs WinBtrfs - an open-source btrfs driver for Windows 项目地址: https://gitcode.com/gh_mirrors/bt/btrfs 一、问题场景&#xff1a;双系统用户的文件访问困境 痛点直击&#xff1a;当Wi…...

LeetCode 1143. Longest Common Subsequence 题解

LeetCode 1143. Longest Common Subsequence 题解 题目描述 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长公共子序列的长度。 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删除某些字符&#xff08;也可以…...

提示词合集【自用】

遇到什么问题 用什么方法解决的 为什么不用别的方法 还有没有更好的方法这是一个{简要描述}&#xff0c;请根据以下方式&#xff0c;帮助我学习整个代码库&#xff1a; 项目结构 - 编译方式 - 入口 - 核心逻辑 - 时序图 - 各个步骤关键实现函数。 每次回复只聚焦其中一个部分&a…...

Windows10下PaddleOCR与Python3.8.5的完美搭配:从安装到实战OCR识别

Windows10下PaddleOCR与Python3.8.5的深度实践指南 在数字化办公和自动化流程日益普及的今天&#xff0c;光学字符识别&#xff08;OCR&#xff09;技术已经成为从图像中提取文本信息的重要工具。PaddleOCR作为百度开源的OCR工具库&#xff0c;凭借其出色的识别准确率和易用性…...

如何用STM32CubeMX快速配置Simulink硬件在环项目?STM32G4xx实战演示

STM32CubeMX与Simulink硬件在环开发实战&#xff1a;从零构建电机控制验证平台 当工程师需要验证一个新型电机控制算法时&#xff0c;传统方式往往需要经历PCB设计、焊接调试、反复烧录的漫长周期。而现在&#xff0c;通过STM32CubeMX与Simulink的硬件在环&#xff08;HIL&…...

安卓梦幻互通专用多开切换器|回合制手游多账号快速切换工具(附详细图文教程)

温馨提示&#xff1a;文末有联系方式工具核心定位&#xff1a;安全纯净&#xff0c;专注高效切换 本工具为专为安卓平台设计的轻量级多账号切换解决方案&#xff0c;全程绿色免安装插件&#xff0c;界面无任何广告干扰&#xff0c;严格遵循隐私规范——不访问、不读取、不上传任…...

yz-bijini-cosplay效果惊艳展示:高精度布料褶皱、金属反光、发丝细节呈现

yz-bijini-cosplay效果惊艳展示&#xff1a;高精度布料褶皱、金属反光、发丝细节呈现 基于通义千问Z-Image底座与yz-bijini-cosplay专属LoRA的RTX 4090专属Cosplay风格文生图系统&#xff0c;为Cosplay创作带来了革命性的突破。这个系统不仅支持LoRA动态无感切换和多训练步数版…...

Qwen3.5-9B教程:Gradio队列机制+并发请求限流配置方法

Qwen3.5-9B教程&#xff1a;Gradio队列机制并发请求限流配置方法 1. 模型概述与环境准备 Qwen3.5-9B是一款拥有90亿参数的开源大语言模型&#xff0c;具备强大的逻辑推理、代码生成和多轮对话能力。其多模态变体Qwen3.5-9B-VL支持图文输入&#xff0c;并能处理长达128K token…...

告别B站缓存格式困扰:m4s-converter让视频文件处理效率提升80%

告别B站缓存格式困扰&#xff1a;m4s-converter让视频文件处理效率提升80% 【免费下载链接】m4s-converter 一个跨平台小工具&#xff0c;将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 一、痛点直击&#xf…...