mysql update upper_SQL性能优化-upper函数

背景

最近对生产上最为耗时的几条sql语句进行分析优化,发现最为耗时的几条sql中都出现了upper函数,通过分析它们的执行计划初步估计是由于upper函数的使用导致的性能低下,所以选其中一句比较简单的sql进行了测试和分析。

sql语句如下:

SELECT CIFSTATE,CIFSEQ,CIFNAME,

EMAIL,MOBILEPHONE1,CIFNO

from

PER.zx_pcif

where upper(IDNO)=upper(?)

这条sql的功能是从pcif表中通过IDNO身份证号来查询客户个人信息,整个sql比较简单,但是执行的平均耗时却达到了3.69秒, 其他耗时3.7秒和3.8秒的sql也是简单的select查询操作。

性能分析

初步分析

通过分析这些sql语句的执行计划,如下图所示:

7b72b0e0d29b

执行计划

发现sql整个执行计划中,第一步通过索引来查询记录最为消耗性能,占比达到99%。而sql中是通过设置 where upper(IDNO)=upper(?) 来进行查找,所以初步推断是由于upper()函数的使用导致了性能的下降。为此搭建了测试环境对upper()函数性能进行了验证。

测试验证

实验环境:

系统:MacBook Pro 处理器:2.2GHZ Intel Core i7内存:16G

数据库:MySql 5.7.13 数据量:500万

测试流程:

1.建立表user,其主要主要字段如下:

7b72b0e0d29b

测试表

其中id为主键,idno为身份证号,在idno上建立索引。

2.向表user中插入随机生成的500万条记录;

3.使用uppper()函数来执行查找,sql如下:

select * from user where upper(idno) = upper('12010419870329934X');

执行结果如下:

7b72b0e0d29b

upper

结果显示总共花费的时间为2.066秒。

4.不使用uppper()函数来执行查找,sql如下:

select * from user where idno = '52262319560201341X';

执行结果如下:

7b72b0e0d29b

不使用upper

结果显示总共花费的时间为0.00042秒

结果分析:

7b72b0e0d29b

结果对比

数据显示使用uppder()函数的耗时是不使用uppder()的4919倍,所以upper函数的使用会严重影响sql的执行效率。

优化方案

方案一

将现在数据库表中IDNO字段数据全部转为大写,然后执行sql之前,将参数转为大写,最后在sql中用“=”来执行查询。

方案二

数据库中数据维持现状,然后执行sql之前,将身份证号参数分别转为大小写两个参数,最后在sql中用“=”和“or”进行组合执行查询。

### MySQL UPPER 函数的用法 `UPPER()` 是 MySQL 中的一个字符串处理函数,用于将给定的字符串转换为大写形式。该函数接受单个参数,即要被转换成大写的字符串或列名。 以下是 `UPPER()` 的基本语法: ```sql SELECT UPPER(string_expression); ``` 其中 `string_expression` 可以是一个具体的字符串或者数据库中的某一列[^1]。 #### 示例 1:对固定字符串应用 `UPPER()` 如果需要将固定的字符串转为大写,可以这样操作: ```sql SELECT UPPER('hello world'); -- 结果: HELLO WORLD ``` #### 示例 2:对表中某列的数据应用 `UPPER()` 假设有一个名为 `employees` 的表,其中有一列表示员工名字叫 `name`。可以通过如下方式查询并将所有名字转换为大写: ```sql SELECT name, UPPER(name) AS uppercase_name FROM employees; -- 假设数据中有 'john doe', 则结果会显示 'JOHN DOE' ``` #### 示例 3:结合其他 SQL 子句使用 `UPPER()` 可以在条件语句中嵌套 `UPPER()` 来忽略大小写差异进行匹配。例如查找姓氏为 "Smith" 的记录而不区分大小写: ```sql SELECT * FROM employees WHERE UPPER(last_name) = 'SMITH'; ``` 注意,在实际开发过程中,虽然可以直接在 `WHERE` 子句里调用 `UPPER()` 或者类似的函数来实现不敏感比较,但如果频繁执行这样的查询可能会降低性能,因为索引可能无法有效利用[^2]。 另外需要注意的是,当存储过程或触发器涉及临时变量时,这些局部定义的变量不需要像全局用户定义变量那样加前缀 '@'[如 ^2 所述];但是如果你确实需要用到带有 '@' 符号声明的会话级变量,则需按照标准书写方法正确引用它们。 最后提醒一点关于文件校验和计算方面的小技巧——假如下载了一个 RPM 包并想验证其完整性,那么就可以借助 Linux 下命令行工具 `md5sum` 完成哈希值对比工作,就像例子展示的一样[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值