使用游标和临时表时MySQL存储过程性能问题

时间:2016-11-18 14:57:37

标签: mysql performance stored-procedures cursor temp-tables

我尝试用存储的SQL过程替换使用DB运行多个请求的重型Java方法。 它正在开展工作,但我预计会有更高的性能提升。 过程的逻辑(以及Java方法):

  1. 从table1(目的)获取ID列表
  2. 迭代列表并从table2(记录)获取每个id的字段的平均值
  3. 返回列表 对id / average_value
  4. 程序中是否存在效率问题?

    DROP PROCEDURE IF EXISTS test1.getGeneralAverage;
    CREATE DEFINER=root@localhost PROCEDURE getGeneralAverage()
      BEGIN
        DECLARE p_id BIGINT(20);
        DECLARE exit_loop BOOLEAN;
        DECLARE cur CURSOR FOR
              SELECT purpose_id FROM purpose
                  WHERE purpose.type = 'GENERAL'
                    AND (SELECT COUNT(*) > 0 FROM record
                          WHERE record.purpose_id=purpose.purpose_id) is true;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
        CREATE TEMPORARY TABLE IF NOT EXISTS general_average
                (id BIGINT(20), average DOUBLE) ENGINE=memory;
        TRUNCATE TABLE general_average;
        OPEN cur;
        average_loop: LOOP
          FETCH cur INTO p_id;
          INSERT INTO test1.general_average (id, average)
               VALUES (p_id, (SELECT AVG(amount) FROM record
                                WHERE record.purpose_id=p_id));
          IF exit_loop THEN
            CLOSE cur;
            LEAVE average_loop;
          END IF;
        END LOOP average_loop;
        INSERT INTO test1.general_average (id, average)
             VALUES (0,
               (select avg(amount) from record where purpose_type='CUSTOM'));
        SELECT * FROM general_average;
      END
    

1 个答案:

答案 0 :(得分:1)

要改变的几种模式......

  • 尽量避免CURSORs;通常,整个操作可以使用单个SQL语句完成。那会更快。

  • INSERT ... VALUES (0, ( SELECT ... ) ) - > INSERT ... SELECT 0, ...

  • 只需提供结果,就不要使用TEMP表。在您的情况下,您可能需要UNION ALL一次交付两个块。