2017-02-08 13 views
0

ステータスが非固有の電子メールが6100万件あります。 この電子メールは、ステータス別にロジックで重複排除する必要があります。postgresqlプロシージャを最適化する方法

ストアドプロシージャを書きますが、このプロシージャは長く実行されます。

この手順の実行時間をどのように最適化できますか?

CREATE OR REPLACE FUNCTION public.load_oxy_emails() RETURNS boolean AS $$ 

DECLARE 
     row record; 
     rec record; 
     new_id int; 
BEGIN 
     FOR row IN SELECT * FROM oxy_email ORDER BY id LOOP 
       SELECT * INTO rec FROM oxy_emails_clean WHERE email = row.email; 
       IF rec IS NOT NULL THEN 
         IF row.status = 3 THEN 
           UPDATE oxy_emails_clean SET status = 3 WHERE id = rec.id; 
         END IF; 
       ELSE 
         INSERT INTO oxy_emails_clean(id, email, status) VALUES(nextval('oxy_emails_clean_id_seq'), row.email, row.status); 
         SELECT currval('oxy_emails_clean_id_seq') INTO new_id; 
         INSERT INTO oxy_emails_clean_websites_relation(oxy_emails_clean_id, website_id) VALUES(new_id, row.website_id); 
       END IF; 
     END LOOP; 
     RETURN true; 
END; 
$$ 
LANGUAGE 'plpgsql'; 
+1

'私はどのように最適化することができます:

update oxy_emails_clean oec SET status = 3 from oxy_email oe where oe.id = oec.id and oe.status = 3; 

行のコピーがCTEsのチェーンを使用して行うことができます。

状態の変化を簡単に単一のステートメントを使用して行うことができますこのプロシージャの実行時間? '**カーソル/ループを持つプロシージャを使用していない**。代わりに、2つの別々のSQL文を使用することができます(おそらく、連鎖したCTEによって一緒に接着されます) – wildplasser

答えて

4

どのように私は、この手順の実行時間を最適化することができますか?

ループを使用しないでください。

行ごとの処理(「スロー・バイ・スロー」とも呼ばれる)は、ほとんどの場合、1つのステートメントで多数の行を「一度に」処理する場合、大量の変更を行うのが非常に遅いです。

with to_copy as (
    select * 
    from oxy_email 
    where status <> 3 --<< all those that have a different status 
), clean_inserted as (
    INSERT INTO oxy_emails_clean (id, email, status) 
    select nextval('oxy_emails_clean_id_seq'), email, status 
    from to_copy 
    returning id; 
) 
insert oxy_emails_clean_websites_relation (oxy_emails_clean_id, website_id) 
select ci.id, tc.website_id 
from clean_inserted ci 
    join to_copy tc on tc.id = ci.id; 
関連する問題