详解Mysql 函数调用优化


Posted in MySQL onApril 07, 2021

函数调用优化

MySQL函数在内部被标记为确定性或不确定性。如果给定参数固定值的函数可以为不同的调用返回不同的结果,则它是不确定的。不确定函数的示例: RAND()UUID()

如果某个函数被标记为不确定的,则将WHERE针对每一行(从一个表中选择时)或行的组合(从多表联接中选择时)评估子句中对该函数的引用。

MySQL还根据参数的类型(参数是表列还是常量值)确定何时评估函数。每当表列更改值时,都必须评估将表列作为参数的确定性函数。

非确定性函数可能会影响查询性能。例如,某些优化可能不可用,或者可能需要更多锁定。以下讨论使用 RAND()但也适用于其他不确定性函数。

假设一个表t具有以下定义:

CREATE TABLE t (id INT NOT NULL PRIMARY KEY, col_a VARCHAR(100));

考虑以下两个查询:

SELECT * FROM t WHERE id = POW(1,2);
SELECT * FROM t WHERE id = FLOOR(1 + RAND() * 49);

由于与主键的相等性比较,两个查询似乎都使用了主键查找,但这仅适用于第一个查询:

  • 第一个查询始终最多产生一行,因为POW()带有常量参数的常量是一个常量值,并用于索引查找。
  • 第二个查询包含一个使用非确定性函数的表达式,该表达式 RAND()在查询中不是常量,但实际上对表的每一行都有一个新值t。因此,查询读取表的每一行,评估每一行的谓词,并输出主键与随机值匹配的所有行。根据id列值和RAND()序列中的值, 它可以是零行,一行或多行 。

非确定性的影响不仅限于 SELECT陈述。该 UPDATE语句使用非确定性函数来选择要修改的行:

UPDATE t SET col_a = some_expr WHERE id = FLOOR(1 + RAND() * 49);

大概目的是最多更新主键与表达式匹配的一行。但是,它可能会更新零,一或多个行,具体取决于 id列值和RAND()序列中的值 。

刚刚描述的行为对性能和复制有影响:

  • 由于不确定函数不会产生恒定值,因此优化器无法使用其他可能适用的策略,例如索引查找。结果可能是表扫描。
  • InnoDB 可能升级为范围键锁,而不是为一个匹配的行获取单行锁。
  • 无法确定执行的更新对于复制是不安全的。

困难源于RAND()对表的每一行都对函数进行一次评估的事实 。为了避免进行多功能评估,请使用以下技术之一:

  • 将包含不确定性函数的表达式移到单独的语句,将值保存在变量中。在原始语句中,将表达式替换为对变量的引用,优化器可以将该变量视为常量值:
SET @keyval = FLOOR(1 + RAND() * 49);
UPDATE t SET col_a = some_expr WHERE id = @keyval;
  • 将随机值分配给派生表中的变量。此技术使变量在WHERE子句中的比较中使用之前被分配一个值 :
SET optimizer_switch = 'derived_merge=off';
UPDATE t, (SELECT @keyval := FLOOR(1 + RAND() * 49)) AS dt
SET col_a = some_expr WHERE id = @keyval;

如前所述,该WHERE子句中的不确定性表达式 可能会阻止优化并导致表扫描。但是,WHERE如果其他表达式是确定性的,则可以部分优化该子句。例如:

SELECT * FROM t WHERE partial_key=5 AND some_column=RAND();

如果优化器可以partial_key用来减少所选行的集合, RAND()则执行的次数更少,这可以减少不确定性对优化的影响。

以上就是详解Mysql 函数调用优化的详细内容,更多关于Mysql 函数调用优化的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
Mysql 性能监控及调优
Apr 06 MySQL
MySQL sql_mode的使用详解
May 08 MySQL
mysql对于模糊查询like的一些汇总
May 09 MySQL
mysql5.7使用binlog 恢复数据的方法
Jun 03 MySQL
mysql备份策略的实现(全量备份+增量备份)
Jul 07 MySQL
Prometheus 监控MySQL使用grafana展示
Aug 30 MySQL
详解MySql中InnoDB存储引擎中的各种锁
Feb 12 MySQL
一条慢SQL语句引发的改造之路
Mar 16 MySQL
mysql 获取时间方式
Mar 20 MySQL
MySQL Server层四个日志的实现
Mar 31 MySQL
Mysql 数据库中的 redo log 和 binlog 写入策略
Apr 26 MySQL
MySQL实现字段分割一行转多行的示例代码
Jul 07 MySQL
MySQL复制问题的三个参数分析
Apr 07 #MySQL
MySQL pt-slave-restart工具的使用简介
Apr 07 #MySQL
MySQL主从复制断开的常用修复方法
Apr 07 #MySQL
MySQL infobright的安装步骤
Apr 07 #MySQL
MySQL表的增删改查基础教程
mysql批量新增和存储的方法实例
Apr 07 #MySQL
Mysql 性能监控及调优
You might like
php5新改动之短标记启用方法
2008/09/11 PHP
php多个文件及图片上传实例详解
2014/11/10 PHP
PHP使用缓存即时输出内容(output buffering)的方法
2015/08/03 PHP
Zend Framework教程之Application和Bootstrap用法详解
2016/03/10 PHP
Laravel 5.4向IoC容器中添加自定义类的方法示例
2017/08/15 PHP
Yii框架日志操作图文与实例详解
2019/09/09 PHP
[对联广告] JS脚本类
2006/08/27 Javascript
jQuery源码分析之Event事件分析
2010/06/07 Javascript
GreyBox技术总结(转)
2010/11/23 Javascript
两个数组去重的JS代码
2013/12/04 Javascript
javascript实现存储hmtl字符串示例
2014/04/25 Javascript
jquery实现的一个简单进度条效果实例
2014/05/12 Javascript
JSON格式的键盘编码对照表
2015/01/29 Javascript
flash+jQuery实现可关闭及重复播放的压顶广告
2015/04/15 Javascript
JavaScript人脸识别技术及脸部识别JavaScript类库Tracking.js
2015/09/14 Javascript
KnockoutJS 3.X API 第四章之数据控制流with绑定
2016/10/10 Javascript
基于js实现checkbox批量选中操作
2016/11/22 Javascript
浅析上传头像示例及其注意事项
2016/12/14 Javascript
jquery——九宫格大转盘抽奖实例
2017/01/16 Javascript
使用Vant完成Dialog弹框案例
2020/11/11 Javascript
[00:09]DOTA2新版本PA至宝特效动作展示
2014/11/19 DOTA
[59:15]完美世界DOTA2联赛PWL S2 LBZS vs FTD.C 第一场 11.20
2020/11/20 DOTA
[51:50]完美世界DOTA2联赛 Magma vs GXR 第一场 11.07
2020/11/10 DOTA
浅析PHP与Python进行数据交互
2018/05/15 Python
python 将print输出的内容保存到txt文件中
2018/07/17 Python
python绘制散点图并标记序号的方法
2018/12/11 Python
Django之使用内置函数和celery发邮件的方法示例
2019/09/16 Python
Python将列表中的元素转化为数字并排序的示例
2019/12/25 Python
基于SpringBoot构造器注入循环依赖及解决方式
2020/04/26 Python
CSS3使用transition实现的鼠标悬停淡入淡出
2015/01/09 HTML / CSS
2014新年元旦活动策划方案
2014/02/18 职场文书
工作睡觉检讨书
2014/02/25 职场文书
《美丽的田园》教学反思
2014/03/01 职场文书
《鲁班和橹板》教学反思
2014/04/27 职场文书
《风娃娃》教学反思
2016/02/18 职场文书
教你使用vscode 搭建react-native开发环境
2021/07/07 Javascript