8.2.1.20 Function Call Optimization函数调用优化

MySQL functions are tagged internally as deterministic or nondeterministic. MySQL函数在内部被标记为确定性或非确定性。A function is nondeterministic if, given fixed values for its arguments, it can return different results for different invocations. 函数是不确定的,如果给定其参数的固定值,它可以为不同的调用返回不同的结果。Examples of nondeterministic functions: RAND(), UUID().非确定性函数的示例:RAND()UUID()

If a function is tagged nondeterministic, a reference to it in a WHERE clause is evaluated for every row (when selecting from one table) or combination of rows (when selecting from a multiple-table join).如果某个函数被标记为不确定函数,则WHERE子句中对该函数的引用将针对每一行(从一个表中选择时)或行的组合(从多个表联接中选择时)进行求值。

MySQL also determines when to evaluate functions based on types of arguments, whether the arguments are table columns or constant values. MySQL还根据参数类型确定何时对函数求值,参数是表列还是常量值。A deterministic function that takes a table column as argument must be evaluated whenever that column changes value.当表列的值发生变化时,必须对以该列为参数的确定性函数求值。

Nondeterministic functions may affect query performance. For example, some optimizations may not be available, or more locking might be required. 非确定性函数可能会影响查询性能。例如,某些优化可能不可用,或者可能需要更多的锁定。The following discussion uses RAND() but applies to other nondeterministic functions as well.下面的讨论使用RAND(),但也适用于其他非确定性函数。

Suppose that a table t has this definition:假设表t具有以下定义:

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

Consider these two queries:考虑这两个查询:

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

Both queries appear to use a primary key lookup because of the equality comparison against the primary key, but that is true only for the first of them:由于与主键的相等性比较,这两个查询似乎都使用主键查找,但这仅适用于第一个查询:

The effects of nondeterminism are not limited to SELECT statements. 不确定性的影响不限于SELECT语句。This UPDATE statement uses a nondeterministic function to select rows to be modified:UPDATE语句使用不确定函数选择要修改的行:

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

Presumably the intent is to update at most a single row for which the primary key matches the expression. 大概目的是更新主键与表达式匹配的最多一行。However, it might update zero, one, or multiple rows, depending on the id column values and the values in the RAND() sequence.但是,它可能会更新零行、一行或多行,具体取决于id列值和RAND()序列中的值。

The behavior just described has implications for performance and replication:刚才描述的行为对性能和复制有影响:

The difficulties stem from the fact that the RAND() function is evaluated once for every row of the table. 困难源于这样一个事实:RAND()函数对表中的每一行求值一次。To avoid multiple function evaluations, use one of these techniques:要避免多个功能评估,请使用以下技术之一:

As mentioned previously, a nondeterministic expression in the WHERE clause might prevent optimizations and result in a table scan. 如前所述,WHERE子句中的不确定表达式可能会阻止优化并导致表扫描。However, it may be possible to partially optimize the WHERE clause if other expressions are deterministic. 但是,如果其他表达式是确定性的,则可以部分优化WHERE子句。For example:例如:

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

If the optimizer can use partial_key to reduce the set of rows selected, RAND() is executed fewer times, which diminishes the effect of nondeterminism on optimization.如果优化器可以使用partial_key来减少所选行的集合,则RAND()的执行次数会减少,从而减少不确定性对优化的影响。