2017-07-17 15 views
0

テスト目的で、本番サーバーからローカルサーバーにデータをダンプするだけです。私たちのアプリは、SQLの約300行のストアドプロシージャを使用しています。この手順はサーバーデータベースで正常に動作しますが、ローカルデータベースで実行するたびに常時実行されてしまいます。なぜ誰かが立ち往生してしまった理由について誰にも分かりません。 これはデータをダンプする私のコマンドです。ここデータベースを移動した後にストアドプロシージャが停止する

pg_dump --host localhost --port 5432 --username postgres --dbname test-new >D:\test5.sql 

psql --host localhost --port 5432 --username postgres --dbname test-qa < file.sql 

ストアプロシージャを使用すると、コード内で改善することができるものを見たら、私を提案してください、また

CREATE OR REPLACE FUNCTION public.insert_hm_ticket_statistic(v_sprint_id bigint) 
    RETURNS integer 
LANGUAGE plpgsql 
AS $$ 

DECLARE 

    v_ticket    INT; 
    v_startsprint_date DATE; 
    v_end_date   DATE; 
    v_current_date  DATE; 
    v_first_activity_date DATE; 
    v_started    DATE; 

    v_sprint_setting  VARCHAR(255); 

    v_time_spent_second FLOAT; 
    v_remaining_estimate FLOAT; 
    v_time_logged_tmp  FLOAT; 

    v_has_log    INT; 
    v_time_logged_tk  FLOAT; 
    v_oe_tk    INT; 
    v_has_past_sprint  INT; 

    v_oe_sprint   INT; 
    v_complete_of_sprint FLOAT; 
    v_oe_tk_burnt   FLOAT; 
    v_oe_sprint_burnt  FLOAT; 
    v_project_complete FLOAT; 
    v_complete_tk   FLOAT; 

    rl_cursor CURSOR FOR SELECT 
          tk.id, 
          tk.has_past_sprint, 
          cast(first_activity_date AS DATE) 
         FROM hm_ticket tk 
         WHERE sprint = v_sprint_id AND deleted = 0; 

BEGIN 

    -- find start date and end date of sprint 
    SELECT 
    cast(start_date AS DATE), 
    cast(end_date AS DATE) 
    INTO v_startsprint_date, v_end_date 
    FROM hm_sprint 
    WHERE id = v_sprint_id AND status <> 'future'; 



    -- find sprint setting 
    IF NOT exists(SELECT d.burn_down_statuses 
       FROM hm_sprint x, hm_setting c, hm_burn_down_status d 
       WHERE c.id = d.setting AND x.setting = c.id AND x.id = v_sprint_id) 
    THEN 
    v_sprint_setting :='xxx'; 
    ELSE 
    SELECT string_agg(d.burn_down_statuses, ',') 
    INTO v_sprint_setting 
    FROM hm_sprint x, hm_setting c, hm_burn_down_status d 
    WHERE c.id = d.setting AND x.setting = c.id AND x.id = v_sprint_id; 
    END IF; 

    raise notice 'v_sprint_setting %', v_sprint_setting; 

    OPEN rl_cursor; 
    LOOP 

    FETCH rl_cursor INTO v_ticket, v_has_past_sprint, v_first_activity_date; 
    raise notice 'v_ticket: %', v_ticket; 

    EXIT WHEN NOT FOUND; 

    /*select cast(min(started) as date) into v_started 
     from hm_worklog 
     where ticket=v_ticket and cast(started as date) between v_startsprint_date and v_end_date; 

     if v_started is null then v_current_date:=v_startsprint_date; 
     else 
     v_current_date:=v_started; 
     end if;*/ 

    v_current_date:=v_startsprint_date; 

    --- calculate remaining estimate, time logged of ticket 
    IF v_has_past_sprint = 0 
    THEN 
     SELECT 
     coalesce(remaining_estimate, 0), 
     coalesce(time_logged, 0) 
     INTO v_remaining_estimate, v_time_logged_tk 
     FROM hm_ticket 
     WHERE id = v_ticket; 

    ELSE 
     SELECT coalesce(time_logged, 0) 
     INTO v_time_logged_tmp 
     FROM hm_ticket 
     WHERE id = v_ticket; 
     -------------------------------------- 
     SELECT 
     coalesce(remaining_estimate, 0), 
     v_time_logged_tmp - coalesce(time_logged, 0) 
     INTO v_remaining_estimate, v_time_logged_tk 
     FROM hm_ticket_past_sprint 
     WHERE ticket = v_ticket; 

    END IF; 

    raise notice '----------v_has_past_sprint: %', v_has_past_sprint; 
    raise notice '----------v_time_logged_tmp: %', v_time_logged_tmp; 
    raise notice '----------v_time_logged_tk: %', v_time_logged_tk; 
    raise notice '----------v_remaining_estimate: %', v_remaining_estimate; 

    -- calculate oe of ticket 
    IF v_has_past_sprint = 0 
    THEN 
     SELECT cast(CASE WHEN coalesce(original_estimate, 0) = 0 
     THEN coalesce(time_logged, 0) 
        ELSE original_estimate 
        END 
        AS FLOAT) 
     INTO v_oe_tk 
     FROM hm_ticket 
     WHERE id = v_ticket; 
    ELSE 
     SELECT coalesce(time_logged, 0) 
     INTO v_time_logged_tmp 
     FROM hm_ticket 
     WHERE id = v_ticket; 
     -------------------------------------- 
     SELECT cast(CASE WHEN coalesce(original_estimate, 0) = 0 
     THEN v_time_logged_tmp - coalesce(time_logged, 0) 
        ELSE original_estimate 
        END 
        AS FLOAT) 
     INTO v_oe_tk 
     FROM hm_ticket_past_sprint 
     WHERE ticket = v_ticket; 

    END IF; 

    raise notice 'v_oe_tk: %',v_oe_tk; 


    /*########################################################################## START TO LOOP CURRENT DATE #############################################################################*/ 

    WHILE v_current_date <= v_end_date LOOP 
     --- calculate time_spent_seconds from start sprint 
     IF NOT exists(SELECT id 
        FROM hm_worklog 
        WHERE ticket = v_ticket AND cast(started AS DATE) BETWEEN v_startsprint_date AND v_current_date) 
     THEN 
     v_time_spent_second:=0; 
     ELSE 
     SELECT cast(sum(time_spent_seconds) AS FLOAT) 
     INTO v_time_spent_second 
     FROM hm_worklog 
     WHERE ticket = v_ticket AND cast(started AS DATE) BETWEEN v_startsprint_date AND v_current_date 
     GROUP BY ticket; 
     END IF; 

     raise notice 'v_time_spent_second: %', v_time_spent_second; 

     --calculate % complete of ticket/day 

     IF NOT v_current_date = v_end_date THEN 
     IF NOT exists(SELECT date FROM hm_ticket_history WHERE ticket = v_ticket AND cast(date AS DATE) = v_current_date) 
     then 
      -- FIND STATUS OF TICKET IN SETTING. 0: NO STATUS EXIST -> FORMULAR SHOULD BE APPLIED , <>0 : EXIST--> SET COMPLETE TK = 0 

      SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0) 
      THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80 
       WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0 
       WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0 
       ELSE round(cast(v_time_spent_second * 100/(v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2) 
       END 
       ELSE 100 
       END AS complete 
      INTO v_complete_tk 
      FROM hm_ticket 
      WHERE id = v_ticket; 
     ELSE 
      SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0) 
      THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80 
       WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0 
       WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0 
       ELSE round(cast(v_time_spent_second * 100/(v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2) 
       END 
       ELSE 100 
       END AS complete 
      INTO v_complete_tk 
      FROM hm_ticket_history 
      WHERE ticket = v_ticket AND cast("date" AS DATE)= v_current_date; 
     END IF; 
     ELSE 
     --NOTE: IF V_CURRENT_DATE == END-DATE-OF-SPRINT, COMPLETE % WILL BE CALCULATED BASE ON LATEST TICKET STATUS, NOT LAST-DAY-OF-SPRINT TICKET STATUS 
     IF NOT exists(SELECT date FROM hm_ticket_history WHERE ticket = v_ticket AND cast(date AS DATE) = v_current_date) 
     then 
      SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0) 
      THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80 
       WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0 
       WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0 
       ELSE round(cast(v_time_spent_second * 100/(v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2) 
       END 
       ELSE 100 
       END AS complete 
      INTO v_complete_tk 
      FROM hm_ticket 
      WHERE id = v_ticket; 
     else 
      SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0) 
      THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80 
       WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0 
       WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0 
       ELSE round(cast(v_time_spent_second * 100/(v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2) 
       END 
       ELSE 100 
       END AS complete 
      INTO v_complete_tk 
      FROM hm_ticket_history 
      WHERE ticket = v_ticket order by date desc limit 1; 
     END IF; 
     END IF; 


     if v_complete_tk > 100 then v_complete_tk := 100; 
     end if; 

     raise notice 'v_sprint_setting: %', v_sprint_setting; 
     raise notice 'v_complete_tk: %', v_complete_tk; 
     raise notice '---------------------------------'; 

     -- check has log 
     IF exists(SELECT id 
       FROM hm_worklog 
       WHERE cast(started AS DATE) = cast(v_current_date AS DATE) AND ticket = v_ticket) 
     THEN 
     v_has_log := 1; 
     ELSE 
     v_has_log := 0; 
     END IF; 

     --raise notice 'v_has_log: %', v_has_log; 

     -- calculate oe of sprint 
     SELECT sum(x.oe) 
     INTO v_oe_sprint 
     FROM 
     (
      SELECT CASE WHEN coalesce(original_estimate, 0) = 0 
      THEN coalesce(time_logged, 0) 
       ELSE coalesce(original_estimate, 0) 
       END oe 
      FROM hm_ticket 
      WHERE sprint = v_sprint_id AND cast(first_activity_date AS DATE) <= v_current_date 
       AND has_past_sprint = 0 

      UNION ALL 

      SELECT CASE WHEN coalesce(b.original_estimate, 0) = 0 
      THEN coalesce(a.time_logged - b.time_logged) 
       ELSE coalesce(b.original_estimate, 0) 
       END oe 
      FROM hm_ticket a, hm_ticket_past_sprint b 
      WHERE a.id = b.ticket AND a.sprint = v_sprint_id AND cast(a.first_activity_date AS DATE) <= v_current_date 
       AND a.has_past_sprint = 1 
     ) x; 

     -- raise notice 'v_oe_sprint: %', v_oe_sprint; 

     -- calculate v_oe_tk_burnt 
     SELECT CASE WHEN v_time_spent_second = 0 OR v_oe_tk = 0 
     THEN 0 
      ELSE round(cast((v_time_spent_second * 100/v_oe_tk) AS NUMERIC), 2) 
      END 
     INTO v_oe_tk_burnt; 

     --raise notice 'v_oe_tk_burnt: %', v_oe_tk_burnt; 

     -- calculate v_oe_sprint_burnt 
     IF v_oe_sprint = 0 
     THEN 
     v_oe_sprint_burnt:=100; 
     ELSE 
     SELECT round(cast((v_time_spent_second * 100/v_oe_sprint) AS NUMERIC), 2) 
     INTO v_oe_sprint_burnt; 
     END IF; 

     --raise notice 'v_oe_sprint_burnt: %', v_oe_sprint_burnt; 

     -- calculate v_project_complete 
     IF v_oe_sprint = 0 
     THEN 
     v_project_complete:=100; 
     ELSE 
     SELECT round(cast((v_complete_tk * v_oe_tk/v_oe_sprint) AS NUMERIC), 2) 
     INTO v_project_complete; 
     END IF; 

     -- raise notice 'v_project_complete: %', v_project_complete; 

     IF v_current_date >= v_first_activity_date 
     THEN 
     INSERT INTO hm_ticket_statistic (complete, date, has_log, last_modified, original_estimate_burnt, original_estimate_project_burnt, project_complete, status, ticket, sprint) 
     VALUES 
      (v_complete_tk, cast(v_current_date AS DATE), v_has_log, current_timestamp, v_oe_tk_burnt, v_oe_sprint_burnt, 
      v_project_complete, 1, v_ticket, v_sprint_id) 
     ON CONFLICT (date, ticket, sprint) 
      DO UPDATE 
      SET complete      = v_complete_tk, 
       has_log       = v_has_log, 
       original_estimate_burnt   = v_oe_tk_burnt, 
       original_estimate_project_burnt = v_oe_sprint_burnt, 
       project_complete    = v_project_complete; 
     END IF; 

     v_current_date:= v_current_date + INTERVAL '24 hours'; 

     EXIT WHEN NOT found; 

    END LOOP; 

    END LOOP; 
    CLOSE rl_cursor; 

    RETURN 0; 
END; 

です。

+0

"詰まる"とは何かを分析してみてください。 CPUを使用していませんか?ファイルを作成しませんか?おそらくそれはちょうど長い時間がかかります... –

+0

あなたのデータベースをどのように復元するかを示して、ストアドプロシージャとその呼び出し方法を表示します。また、ロックを待っているかどうかチェックしましたか? https://wiki.postgresql.org/wiki/Lock_Monitoring –

答えて

0

最後にバグが見つかりました。それはデッドロックのバグです、私はあまりにも多くの機能で同期化を使用し、彼らは立ち往生し始めます。プロダクションサーバーはまだ同じ問題を抱えていますが、私はそれを見ません。ですから、私はより選択的に同期化を使用しようとすると、同期化された関数のサイズを減らします。その後、固定されます。

3

ダンプを復元した後、ローカルデータベースでanalyzeを実行してみてください。これにより統計が更新されます。

+1

ダンプを復元するための良い統計は必要ありません。 –

+1

@LaurenzAldbは、ダンプを復元した後、OPがストアドプロシージャを実行しようとしたことを理解しました。 – maniek

+0

ああ、ありがとう。それから、あなたの答えが上にあるかもしれません。 –

関連する問題