2016-11-18 76 views
0

我嘗試用存儲的SQL過程替換運行多個請求的重度Java方法。 它正在完成它的工作,但我期望性能得到更高的改進。 程序的邏輯(以及Java方法):從表1(目的)的ID使用遊標和臨時表時MySQL存儲過程的性能問題

  1. 獲取列表
  2. 迭代列表,並從表2(記錄)字段的平均值爲每個ID
  3. 返回列表對ID的 /AVERAGE_VALUE

是否有手術中的任何效率問題?

DROP PROCEDURE IF EXISTS test1.getGeneralAverage; 
CREATE [email protected] 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

幾種模式改變...

  • 儘量避免CURSORs;通常整個操作可以使用單個SQL語句完成。這將會更快。

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

  • 不要使用臨時表時,你可以簡單地提供的結果。在你的情況下,你可能需要一個UNION ALL一次交付兩個塊。