MySQL如何在查询中加速UDF

时间:2014-04-16 02:15:21

标签: mysql sql user-defined-functions

我有一个包含userID,department,er的表。我创建了一个简单的查询来收集所有这些信息。

SELECT table.userID, table.department, table.er FROM table;

现在,我想对属于同一部门的所有人进行分组并执行此计算

select sum(table.er)/3 as department_er from table group by table.department;

然后在第一个查询中将此结果添加为新列。为此,我创建了一个看起来像这样的UDF

BEGIN
  DECLARE department_er FLOAT;
  set department_er = (select sum(er) from table where table.department = dpt);
  RETURN department_er;
END

然后我在此查询中使用了该UDF

SELECT table.userID, table.department, (select dptER(table.department)/3) as department_er FROM table

我已将我的表编入索引,更复杂的查询从4分钟以上删除到不到1秒。这似乎很简单,但运行10分钟。有没有更好的方法来实现这一点或优化我的UDF?

原谅我的n00b-ness:)

1 个答案:

答案 0 :(得分:1)

在SELECT子句中尝试不带依赖聚合子查询的查询:

select table.userID, 
       table.department as dpt,
       x.department_er 
from table 
join (
  select department,
         (sum(table.er)/3) As department_er 
  from table
  group by department
) x
ON x.department = table.department

无法优化此UDF功能。也许它似乎适用于简单的查询,但通常它会损害您的数据库性能。

想象一下,我们有一个像这样的查询:

SELECT ....., UDF( some parameters )
FROM table
....

MySql必须为从此查询中的表中检索到的每条记录调用此函数 如果表包含1000条记录 - 该函数将被触发1000次。
并且函数内的查询也会被触发1000次。
如果是10.000记录 - 那么该函数被称为10.000次。

即使您以这种方式优化此功能,UDF将快2倍,上述查询仍将触发该功能1000次。
如果500个用户拥有相同的部门 - 每个用户仍然会调用500次,并为每个用户计算相同的值 499次冗余通话,因为只需1次通话即可计算此值。

优化此类查询的唯一方法是采用"内部"从UDF函数中查询并使用连接等将其与主查询相结合。