2016-12-23 11 views
0

このプロシージャのポイントは、これらのIDをある種のインデックスに追加することによって、物品の販売時点情報を高速化するために、顧客ごとにIDを更新して生成することですPHONENUMSというテーブル。このInterbaseプロシージャのランタイムを最適化しようとする

このプロシージャはデータの初期化手順ですが、現在このクライアントのデータベースで実行するには最大2日かかります。明らかに、それは待っている間に2日間の休暇を取ってしまうため、休暇はありません。この関数は、customersテーブルのForループを実行するPHONENUM_REFRESH_ALLから実行され、それに応じて各レコードを処理するプロシージャを呼び出します。私は以下の両方の手順を貼り付けました。

私はInterbase PLANAnalyzerを使用して、このプロセスで重い部分を絞り込んでみましたが、1つのレコードを処理しているかのように実行した場合、非常に高速です。プロセスをスピードアップするためにクローズまたはシングルアウトすることはできませんが、私たちは顧客名に似たプロセスを持ち、信じられないほど速く動作しますが、両者を並置しても私には答えられません。そこには非常にゆっくりと実行する原因になるいくつかの眩しい問題はありますか?

forループを実行するマスタープロシージャ。

CREATE PROCEDURE PHONENUM_REFRESH_ALL AS 
declare variable custid varchar(8); 
declare variable KEYWORD varchar(30); 
declare variable AREACODE VARCHAR(3); 
declare variable PRIMARYTEL VARCHAR(8); 
declare variable PRIMARYTELID VARCHAR(8); 
declare variable configdefault varchar(8); 
begin 
    /* 2016-03-16 - Creation */ 

insert into timetracker(time_stamp) values (cast('NOW' as timestamp)); 
    for select custid, areacode, primarytel, PRIMARYTELID 
    from customers 
    where (primarytelid || '' is null or primarytelid || '' = '') 
    and areacode is not null and areacode <> '' 
    and primarytel is not null and primarytel <> '' 
    into :custid, :AREACODE, :primarytel,:PRIMARYTELID do 
    begin 
    select primarytelid from PHONENUM_REFRESH(:CUSTID,:AREACODE,:PRIMARYTEL,'') into :primarytelid; 
    update customers set primarytelid = :primarytelid where custid = :custid; 
    end 
insert into timetracker(time_stamp) values (cast('NOW' as timestamp)); 
END 

PHONENUM_REFRESHプロシージャ(マスタープロシージャから渡された単一のレコードを処理する)。

CREATE PROCEDURE PHONENUM_REFRESH (
    CUSTID VARCHAR(8), 
    AREACODE VARCHAR(3), 
    PRIMARYTEL VARCHAR(8), 
    TRIGG VARCHAR(8) 
) RETURNS (
    PRIMARYTELID VARCHAR(8) 
) AS 
DECLARE VARIABLE NEWTELID INTEGER; 
DECLARE VARIABLE FOUNDTELID VARCHAR(6); 
DECLARE VARIABLE BRANCHID VARCHAR(2); 
DECLARE VARIABLE DBTYPE CHAR(2); 
DECLARE VARIABLE CNT INTEGER; 
DECLARE VARIABLE TELNOTE VARCHAR(40); 
DECLARE VARIABLE GENTELIDPREFIX varchar(2); 

BEGIN 
    /* 2013-07-13 V1.0 - Creation. Procedure is binding customer to an existing phonenum (if not bound), creates it if none is matching. 
    2015-05-04 V1.1 - If matching primarytel is found, update customer's primarytelid 
    2015-07-22 V1.2 - Not updating CUSTOMERS table if called from trigger (TRIGG = 'trIgg') 
    2015-08-20 - To add GENTELIDPREFIX for fixing conversion string error with TELID 
    */  
    /* CustId mandatory */ 
    IF ((CUSTID <> '') AND (CUSTID IS NOT NULL)) THEN 
    BEGIN 
    IF ((TRIGG = '') OR (TRIGG IS NULL)) THEN 
     TRIGG = 'SYSDBA'; 
    /* PRIMARYTELID NOT SET, TRY TO GET ONE */ 
    IF ((AREACODE <> '') AND (PRIMARYTEL <> '')) THEN 
    BEGIN 
     SELECT MIN(TELID) FROM PHONENUMS WHERE AREACODE=:AREACODE AND PRIMARYTEL=:PRIMARYTEL AND CUSTID=:CUSTID INTO :PRIMARYTELID; 

     SELECT F_LEFT(config_value,1) FROM branch_config WHERE branchid = '00' and config_name = 'GEN_TELID_PREFIX' into :GENTELIDPREFIX; 

     /* No PRIMARYTELID found. Go create one with 'PR' */ 
     IF (PRIMARYTELID IS NULL) THEN 
     PRIMARYTELID = ''; 

     IF (PRIMARYTELID = '') THEN 
     BEGIN 
     /* If SF, we force it to use the generators */ 
     SELECT MIN(DBTYPE) FROM DATABASEID INTO :DBTYPE; 
     IF (DBTYPE = 'SF') THEN 
     BEGIN 
      FOUNDTELID='X'; 
      BRANCHID='00'; 
     END 
     ELSE 
     BEGIN 
      SELECT TELID, BRANCHID FROM CTRLFILE WHERE BRANCHID = (SELECT MIN(DBID) FROM DATABASEID) ROWS 1 INTO :FOUNDTELID,:BRANCHID; 
     END 

     IF (FOUNDTELID = 'X') THEN 
     BEGIN 
      SELECT GEN_ID(GENTELID,1) FROM RDB$DATABASE INTO :NEWTELID; 

      if ((GENTELIDPREFIX is not null) AND (GENTELIDPREFIX <> '')) then 
      BEGIN 
      PRIMARYTELID = GENTELIDPREFIX || CAST(NEWTELID AS VARCHAR(7)); 
      END 
      ELSE 
      BEGIN 
      PRIMARYTELID = BRANCHID || CAST(NEWTELID AS VARCHAR(6)); 
      END 
      TELNOTE = ''; 
      select count(*) from phonenums where telid = :PRIMARYTELID into :cnt; 

      IF (CNT = 1) THEN 
      BEGIN 
      /* Whaaaaaat? Twilight zone glitch, gotta save the moment! */ 
      TELNOTE = '(Shifted from telid ' || PRIMARYTELID || ')'; 
      SELECT GEN_ID(GENTELID,1) FROM RDB$DATABASE INTO :NEWTELID; 

      if ((GENTELIDPREFIX is not null) AND (GENTELIDPREFIX <> '')) then 
      BEGIN 
       PRIMARYTELID = GENTELIDPREFIX || CAST(NEWTELID AS VARCHAR(7)); 
      END 
      ELSE 
      BEGIN 
       PRIMARYTELID = BRANCHID || CAST(NEWTELID AS VARCHAR(6)); 
      END 
      END 
      INSERT INTO PHONENUMS (TELID,PRIMARYTEL,AREACODE,TELTYPE,CUSTID,EDU_,TELNOTE) VALUES(:PRIMARYTELID,:PRIMARYTEL,:AREACODE,'PR',:CUSTID,:TRIGG,:TELNOTE); 
     END 
     ELSE 
     BEGIN 
      NEWTELID = CAST(FOUNDTELID AS INTEGER) + 1; 
      if ((GENTELIDPREFIX is not null) AND (GENTELIDPREFIX <> '')) then 
      BEGIN 
      PRIMARYTELID = GENTELIDPREFIX || CAST(NEWTELID AS VARCHAR(7)); 
      END 
      ELSE 
      BEGIN 
      PRIMARYTELID = BRANCHID || CAST(NEWTELID AS VARCHAR(6)); 
      END 
      INSERT INTO PHONENUMS (TELID,PRIMARYTEL,AREACODE,TELTYPE,CUSTID,EDU_) VALUES(:PRIMARYTELID,:PRIMARYTEL,:AREACODE,'PR',:CUSTID,:TRIGG); 
      UPDATE CTRLFILE SET TELID = :NEWTELID WHERE BRANCHID = :BRANCHID; 
     END 

     END 
     ELSE IF (TRIGG <> 'trIgg') THEN 
     BEGIN 
     UPDATE CUSTOMERS SET PRIMARYTELID = :PRIMARYTELID WHERE CUSTID = :CUSTID; 
     END 
    END 

    END 

    SUSPEND; 
    END 

答えて

0

PHONENUMSにレコードを1つずつ挿入することが少し難解です。 CUSTOMERSから必要なレコードを読み込み、何らかのID生成と共に1回のパスで挿入するためのSQLを少し書いてもかまいませんか? CTRLファイルを後で1回のパスで更新することもできます。 または私は何が欠けていますか?

+0

ええ、いくつかの脂肪をカットすることができます、CTRLファイルはブランチごとにあり、50の支店がありますが、2.5mの顧客、それは冗長です。しかし、PHONENUMSへの挿入はどのようにして1回のパスで行うのですか?どのインサートにもジェネレータによって生成されたIDがあります。挿入する前に250万IDの可能性をどのように保存することができますか?その後、idはそれらの値をすべて渡す動的な挿入呼び出しを作成する必要がありますか?私はあなたが何を言っているのか理解していますが、おそらく私がそれを達成できる方法ではありません – Denis

関連する問題