2017-09-26 98 views
0

從兩個sql語句中提取數據後,我插入n行。到目前爲止,我使用了兩種方法,第一種是Cursor,另一種是While循環。嵌套while循環比嵌套遊標佔用更多時間

嵌套遊標:

begin 
    declare userId,taskId int default 0; 
    declare userCnt int default 0; 
    declare c1 cursor for select us_id from us_uxusermaster ; 
    declare continue handler for not found set userCnt=1; 
    open c1; 
    CheckId: loop 
    fetch c1 into userId; 
    if userCnt=1 
    then 
     leave CheckId; 
    end if; 
      Select pl.pl_minTarget into target from pl_planlist pl inner join ap_affiliateplan ap inner join us_uxusermaster us on Find_in_set(pl.pl_id,us.us_planListId) and ap.ap_id =us.us_taskPlanId where us_id=userId and pl.pl_serviceName=2; 
       Begin 
       DECLARE taskId int default 0; 
       Declare taskCnt int default 0; 
       Declare t1 cursor for select tk.tk_id from tk_taskmaster tk where tk.tk_activeTime=AddDate(Current_date(),1) and tk_actStatus=0 and tk_status=1 limit target; 
       Declare continue handler for not found set taskCnt=1; 
       open t1; 
       CheckTask: loop 
       fetch t1 into taskId; 
       if taskCnt=1 
       then 
       leave CheckTask; 
       end if; 

        insert into ut_userstask(ut_tk_id,ut_us_id,ut_edtm,ut_eby) values (taskId,userId,current_timestamp,'Via-Event'); 
       end loop checkTask; 
       close t1; 
       End; 
    end loop CheckId; 
    close c1; 

    end; 

While循環:

begin 
declare taskName,taskCode,description,url,userLevel,TaskStatus,TaskActStatus,Steps,taskId,userId varchar(50); 

declare activationTime,deActivationTime datetime; 

Declare flag,flag2,counts,counts2 int default 0; 
Drop Temporary Table if exists temptrigg; 
Set @rownumber=0; 
Set @rownumber2=0; 
create temporary table temptrigg as(select * from (select (@rownumber := @rownumber + 1) AS newrow, us_id from us_uxusermaster) AS xst); 
select count(*) into counts from temptrigg; 
while(flag<counts) 
Do 
Set flag=flag+1; 
Select us_id into userId from temptrigg where newrow=flag; 

Drop Temporary Table if exists temptrigg2; 
Create temporary table temptrigg2 as(select * from(select (@rownumber2 := @rownumber2 + 1) as newrow2,tk.tk_id from tk_taskmaster tk where tk.tk_activeTime=Current_date() and tk_actStatus=0 and tk_status=1)as xst); 
Select count(*) into Counts2 from temptrigg2; 
While(flag2<Counts2) 
Do 
Set flag2=flag2+1; 
Select tk_id into taskId from temptrigg2 where newrow2=flag2; 

    insert into ut_userstask(ut_tk_id,ut_us_id,ut_edtm,ut_eby) values (taskId,userId,current_timestamp,'Via-Event'); 

End While; 
End While; 

end 

這裏的問題是,while循環正在雙倍時間比光標。我對其未來的結果感到困惑。通過替換嵌套的while循環來遵循遊標會很好。

插入425行遊標需要23.05秒,while循環需要46秒。這兩個時間對我來說都太多了。有沒有其他方法可以提高性能?

很高興知道有沒有。

+2

你有沒有試過縮進你的代碼?這將使它更容易閱讀。無論如何,帶有while循環的版本是在循環內創建和刪除臨時表。我並不感到驚訝,它更慢。我真的很驚訝,它只有2倍的緩慢。 – GolezTrol

+2

到目前爲止,最快的方法是用你想要的所有東西構建一個select語句,然後使用'insert into ut_userstask(...)select ...(...)from ...'來插入值。 – GolezTrol

+0

@GolezTrol有多個用戶和多個任務,每個我都必須插入所有任務。所以它不能被存儲在表中,因爲我會在那裏一團糟。這就是爲什麼我使用光標 – Dashanan

回答

1

我不知道如果我抓住每一個檢查你有沒有(特別是limit),但它會節省很多,如果你能擠它變成一個單一的insert..select這樣的:

Insert into ut_userstask(ut_tk_id,ut_us_id,ut_edtm,ut_eby) 
Select 
    tk.tk_id, 
    us.us_id, 
    current_timestamp, 
    'Via-Event' 
from pl_planlist pl 
inner join ap_affiliateplan ap 
inner join us_uxusermaster us on ap.ap_id = us.us_taskPlanId 
inner join tk_taskmaster tk on tk.tk_activeTime=AddDate(Current_date(),1) and tk_actStatus=0 and tk_status=1 
where 
    pl.pl_serviceName=2 
    and Find_in_set(pl.pl_id,us.us_planListId) 

要記住的其他內容:確保您有適當的索引並儘量避免像FIND_IN_SET這樣的函數。這通常表明您的數據庫不夠標準化,並且使用起來非常慢,因爲它繞過了列上可用的任何索引。

即使你不能在一個select中放置everthing,它仍然可能更快地循環遍歷一個主遊標(例如獲取用戶),併爲遊標的每一行執行insert..select 。

+0

我已經嘗試過這一點,但它不會因爲在where子句中會有多個用戶ID不會讓我回來。 – Dashanan

+0

該檢查可以從where子句中刪除,因爲它已經隱含在內部聯接中。查詢修改。 – GolezTrol

+0

是的,它有一些修改它的工作。感謝這個想法。請投票。 – Dashanan