mysql5.7官网直译SQL语句优化--函数调用的优化

48 篇文章 0 订阅
1.17 Function Call Optimization 函数调用的优化
mysql的函数被标记位确定或者是不确定的函数两大类。一个函数通过固定的入参多次调用返回不同的结果值,则被称为不确定函数,比方说函数RUND(),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);
两个查询看起来都是通过主键id的等于比较操作来查询的,但是实际上只有以第一个是:
>第一个查询总是生成最多一行数据因为函数POW()通过常量参数会得到一个常量值,而且用索引查找,所以最多返回一行值,或者是没有值。
>第二个查询包含了一个表达式其中使用了不确定函数RAND(),也就是不是一个常量在查询中而对于表t中的每一行都是一个新值。所以,查询读取了表中的每行,对每一行做判断,并输出所有和随机值匹配的主键值对应的行。这有可能是0行,1行或者是多行,依赖于id列值和RAND()函数序列的值。
不确定函数的影响不只是select语句。这是update语句使用不确定函数选择行数去修改:
UPDATE t SET col_a = some_expr WHERE id = FLOOR(1 + RAND() * 49);
大概的意图是更新至少一行数据对于和主键匹配的表达式的行。然而他有可能更新0行,1行或者多行,这个由id列的值和rand()函数的值来确定。
刚刚描述的行为影响执行语句和复制任务。
>因为不确定函数不会产生一个常量值,优化器不能使用在其他情况下使用的优化手段,比方说索引扫描。结果就是会产生一个表扫描。
>innoDB也许会升级为间隙锁,而不是一个行锁来匹配一行。
>更新不能确定的完成对于复制是不安全的。
关于RAND()函数对对表中每一行都评估一次,对于这个事实很难阻止。为了避免多函数计算,使用这些技术之一:
1)移动包含不确定函数的条件到一个独立的语句,保存变量值。对于原执行语句,取代表达式通过一个变量引用,那么优化器可以看做一个常量来处理:
SET @keyval = FLOOR(1 + RAND() * 49);
UPDATE t SET col_a = some_expr WHERE id = @keyval;
2)分派变量的随机值到派生表中。这种手段会使得变量被分配一个值,一旦有值,优先使用其值去和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()函数的执行会花费更少的时间,这将减少不确定函数对优化的影响。
到此关于函数调用的优化就结束了,接下来我们要说明的是1.18Row Constructor Expression Optimization
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值