Mysql 未确定函数优化

Mysql函数调用优化

 MySQL函数在内部被标记为确定性或非确定性。非确定性函数如:RAND()、UUID()等,如果给它的参数固定值,它可以对不同的结果返回不同的结果被调用。确定函数如POW(),log()等,如果给它的参数固定值,会返回同一个结果被调用。不确定性函数可能会影响查询性能。

CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT, co_name VARCHAR(100), PRIMARY KEY(id));

INSERT INTO t1(co_name) VALUES('A');
INSERT INTO t1(co_name) VALUES('B');
INSERT INTO t1(co_name) VALUES('C');
INSERT INTO t1(co_name) VALUES('E');
INSERT INTO t1(co_name) VALUES('F');
INSERT INTO t1(co_name) VALUES('G');

 

EXPLAIN
SELECT * FROM t1 WHERE id = POW(1,2);

第一个查询总是产生一行的最大值,因为带有常量参数的POW()是一个常数值,用于索引查找。

EXPLAIN
SELECT * FROM t1 WHERE id = FLOOR(1 + RAND()*10);

第二个查询包含一个使用非确定性函数RAND()的表达式在查询中不是常量,但实际上对于表t的每一行都有一个新值。主键与随机值匹配的。这可能是0行,1行,或者多行。这容易导致查询使用全部扫描。
 
 
非确定函数的影响并不局限于选择语句。此UPDATE语句使用非确定性函数,用于选择要修改的行:
update t1 SET co_name= 'AB' WHERE id = FLOOR(1 + RAND() * 49);
但是,它可能更新零行、一行或多行,具体取决于id列值和RAND()序列中的值。
1. 非确定性函数不会产生常数值,所以优化器不能使用主键索引。
2. 未确定地执行的更新对于复制是不安全的。
3. InnoDB可能升级为一个范围键锁甚至是表锁,而不是对一个匹配的行使用单行锁。
 
为了避免多重函数计算,请使用以下方法:
1. 将包含非确定性函数的表达式保存到变量中。在where条件中使用这个变量。,
优化器可以作为一个常值:
SET @id= FLOOR(1 + RAND() *10);
update t1 set  co_name = 'AB' WHERE id = @id;
 
 
2. 将随机值赋给派生表中的变量,赋值一次,在WHERE子句的比较中使用之前:
 
UPDATE /*+ NO_MERGE(c) */ t1, (SELECT FLOOR(1 + RAND()*10) AS a) AS c
SET co_name = 'AB'
WHERE id = c.a;
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值