MYSQL函数逐渐变慢

时间:2015-06-05 12:31:00

标签: mysql performance function

我通过解析字符串创建了以下函数来输入记录:

DROP FUNCTION IF EXISTS RowPerRow ;
DELIMITER $$
CREATE FUNCTION RowPerRow()
RETURNS VARCHAR(300)
BEGIN
    DECLARE n INT DEFAULT 0 ;
    DECLARE m INT DEFAULT 0 ;
    DECLARE i INT DEFAULT 0 ;
    DECLARE j INT DEFAULT 0 ;
    SELECT count(*) FROM Temp0 INTO n ;
    WHILE i < n DO
        SELECT words INTO m FROM Temp0 LIMIT i, 1 ;
        SET j = 1 ;
        WHILE j <= m DO
            INSERT INTO Temp1 SELECT words,id,api,basin,play,drilltype,tradeflag,score,cnf,fracdate,
                fracdateend,state,county,operator,wellname,prodtype,latitude,
                longitude,datum,depth,water,nonwater,surfactant,tradename,TRIM(Split_Str(tradename, ',', j)) AS tradename_c,
                supplier,purpose,ingredients,cas,additive,fluid 
            FROM Temp0 LIMIT i,1 ;
            SET j = j + 1 ;
        END WHILE ;
        SET i = i + 1 ;
    END WHILE ;
    RETURN '' ;
END ;
$$

随着记录数量的增加,函数会逐渐变慢。

1 个答案:

答案 0 :(得分:0)

如果问题是“什么是另一种方法来做同样的RBAR(逐行激动行)处理,但不会逐渐变慢”,我可以给出一个例子看起来像。

如果words存在上限(最大值),则可以在单个语句中完成相同的结果:

  INSERT INTO Temp1 
         ( words,  id,  api,  basin,  play,  drilltype,  tradeflag  ,score  ,cnf,  fracdate,  fracdateend,  state,  county,  operator,  wellname,  prodtype,  latitude,  longitude,  datum,  depth,  water,  nonwater,  surfactant,  tradename,  supplier,  purpose,  ingredients,  cas,  additive,  fluid
         , tradename_c )
  SELECT t.words,t.id,t.api,t.basin,t.play,t.drilltype,t.tradeflag,t.score,t.cnf,t.fracdate,t.fracdateend,t.state,t.county,t.operator,t.wellname,t.prodtype,t.latitude,t.longitude,t.datum,t.depth,t.water,t.nonwater,t.surfactant,t.tradename,t.supplier,t.purpose,t.ingredients,t.cas,t.additive,t.fluid
         , TRIM(Split_Str(t.tradename, ',', n.i)) AS tradename_c
    FROM Temp0 t
    JOIN (SELECT 1 AS i UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL SELECT 20) n
      ON n.i <= t.words

但是这里是一个过程的例子,它相当于原始过程,除了它使用游标循环而不是重复重新查询Temp0表。请注意,变量的数据类型(接受fetch返回的行中的值)应与SELECT列表中相应表达式的数据类型匹配或兼容。在这里,我将它们全部声明为VARCHAR(100)作为占位符,这些将需要更改以匹配Temp0表中的列。

DELIMITER $$

CREATE FUNCTION RowPerRow_alt()
RETURNS VARCHAR(300)
BEGIN
    -- variables for cursor fetch
    -- the datatype of each variable should match the datatype 
    -- of the expression in SELECT list of the query
    DECLARE v_words        INT;
    DECLARE v_id           VARCHAR(100);
    DECLARE v_api          VARCHAR(100);
    DECLARE v_basin        VARCHAR(100);
    DECLARE v_play         VARCHAR(100);
    DECLARE v_drilltype    VARCHAR(100);
    DECLARE v_tradeflag    VARCHAR(100);
    DECLARE v_score        VARCHAR(100);
    DECLARE v_cnf          VARCHAR(100);
    DECLARE v_fracdate     VARCHAR(100);
    DECLARE v_fracdateend  VARCHAR(100);
    DECLARE v_state        VARCHAR(100);
    DECLARE v_county       VARCHAR(100);
    DECLARE v_operator     VARCHAR(100);
    DECLARE v_wellname     VARCHAR(100);
    DECLARE v_prodtype     VARCHAR(100);
    DECLARE v_latitude     VARCHAR(100);
    DECLARE v_longitude    VARCHAR(100);
    DECLARE v_datum        VARCHAR(100);
    DECLARE v_depth        VARCHAR(100);
    DECLARE v_water        VARCHAR(100);
    DECLARE v_nonwater     VARCHAR(100);
    DECLARE v_surfactant   VARCHAR(100);
    DECLARE v_tradename    VARCHAR(100);
    DECLARE v_supplier     VARCHAR(100);
    DECLARE v_purpose      VARCHAR(100);
    DECLARE v_ingredients  VARCHAR(100);
    DECLARE v_cas          VARCHAR(100);
    DECLARE v_additive     VARCHAR(100);
    DECLARE v_fluid        VARCHAR(100);

    DECLARE j INT DEFAULT 0 ;
    DECLARE v_tradename_c  VARCHAR(100);
    DECLARE done TINYINT(1) DEFAULT 0;

    -- cursor for Temp0
    DECLARE csr CURSOR FOR
      SELECT words,id,api,basin,play,drilltype,tradeflag,score,cnf,fracdate,
             fracdateend,state,county,operator,wellname,prodtype,latitude,
             longitude,datum,depth,water,nonwater,surfactant,tradename,
             supplier,purpose,ingredients,cas,additive,fluid 
        FROM Temp0;
    -- setup NOT FOUND handler    
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;  

    OPEN csr;
    rowloop: LOOP
        FETCH csr INTO v_words,v_id,v_api,v_basin,v_play,v_drilltype,v_tradeflag,v_score,v_cnf,v_fracdate,v_fracdateend,v_state,v_county,v_operator,v_wellname,v_prodtype,v_latitude,v_longitude,v_datum,v_depth,v_water,v_nonwater,v_surfactant,v_tradename,v_supplier,v_purpose,v_ingredients,v_cas,v_additive,v_fluid;
        IF done THEN
            LEAVE rowloop;
        END IF;
        SET j = 1;
        WHILE j <= v_words DO
            -- split tradename and insert row ti Temp1
            SET v_tradename_c = TRIM(Split_Str(v_tradename, ',', j));
            INSERT INTO Temp1 ( words,  id,  api,  basin,  play,  drilltype,  tradeflag  ,score  ,cnf,  fracdate,  fracdateend,  state,  county,  operator,  wellname,  prodtype,  latitude,  longitude,  datum,  depth,  water,  nonwater,  surfactant,  tradename,  supplier,  purpose,  ingredients,  cas,  additive,  fluid,
              tradename_c )
                     VALUES ( v_words,v_id,v_api,v_basin,v_play,v_drilltype,v_tradeflag,v_score,v_cnf,v_fracdate,v_fracdateend,v_state,v_county,v_operator,v_wellname,v_prodtype,v_latitude,v_longitude,v_datum,v_depth,v_water,v_nonwater,v_surfactant,v_tradename,v_supplier,v_purpose,v_ingredients,v_cas,v_additive,v_fluid,
              v_tradename_c );
            SET j = j + 1 ;
        END WHILE;
    END LOOP rowloop;
    CLOSE csr;
    RETURN '' ;
END$$