如何加快通过 Oracle PL/SQL 发送电子邮件的速度?

How to speed up sending emails via Oracle PL/SQL?

我正在通过 Oracle 18c 向 SMTP 服务器发送数千封电子邮件。电子邮件不同。

我在放入作业的循环中使用了以下代码。这段代码效果很好,但是速度很慢。 (我说的是执行时间。)

我想知道有没有办法加快速度。例如,只打开一次 SMTP 连接并在整个循环中使用它。

有人试过类似的东西吗?

谢谢。干杯,

谢谢。

    declare
        Connexion   UTL_SMTP.connection;
        l_boundary  VARCHAR2(50) := '----=*#abc1234321cba#*=';
        -- other variables are declared somewhere else...
    Begin
        Connexion := UTL_SMTP.open_connection(Host, Port);

        UTL_SMTP.AUTH(Connexion,KeyName,KeyValue, 'PLAIN');
        UTL_SMTP.helo(Connexion, Host);
        UTL_SMTP.mail(Connexion, MailFrom_);

        -- Add email
        UTL_SMTP.rcpt(Connexion, EmailAddress);  

        -- Open reader to write data
        UTL_SMTP.open_data(Connexion);

        -- Date
        UTL_SMTP.write_data(Connexion, 'Date: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || UTL_TCP.crlf);

        -- Mail to
        UTL_SMTP.write_data(Connexion, 'To: ' || EmailAddress || UTL_TCP.crlf);   

        -- Subject
        UTL_SMTP.write_raw_data(Connexion, utl_raw.cast_to_raw('Subject:' || Subject_));
        UTL_SMTP.WRITE_DATA(Connexion, UTL_TCP.CRLF);      

        -- Message html  
        UTL_SMTP.write_data(Connexion, '--' || l_boundary || UTL_TCP.crlf);
        UTL_SMTP.write_data(Connexion, 'Content-Type: text/html; charset="UTF-8"' || UTL_TCP.crlf || UTL_TCP.crlf);     
        UTL_SMTP.write_raw_data(Connexion, utl_raw.cast_to_raw(MessageInHTML));                    
        UTL_SMTP.write_data(Connexion, UTL_TCP.crlf || UTL_TCP.crlf);  


        UTL_SMTP.write_data(Connexion, '--' || l_boundary || '--' || UTL_TCP.crlf);
        UTL_SMTP.close_data(Connexion);
        UTL_SMTP.quit(Connexion);   
    end;

基本上答案是这样的:

我结合了两件事:

  • 减少新连接数。
  • 多线程。对我来说,每个循环都是独立的,所以我可以像@Justin Cave 在评论中提到的那样使用多线程。

基本上我创建了一个过程,首先创建一个连接(A 部分),然后循环我的查询以发送电子邮件(B 部分), 最后关闭连接(C部分).

此过程已参数化,因此它 运行 仅在查询的一部分上,以便我可以使用多线程。例如,对于 3 个线程上的 运行,我在查询中添加了一个条件,例如:

  • mod(标识符,3) = 0 或
  • mod(标识符,3) = 1 或
  • mod(标识符,3) = 2

(标识符是数字主键...)

然后我将这个过程插入到不同的作业中以 运行 它在几个线程中。

这里需要注意的是,我不知道 smtp 服务器级别是否存在连接最长生命周期。所以我只使用 50 封邮件的连接,然后我创建了一个新邮件。所以连接时间除以50

我的案例的性能结果:

  • 单线程和 reconnect/disconnect 每个循环到 smtp 服务器:184 秒
  • 单线程,每 50 封邮件重新连接:78 秒
  • 3 个线程并每 50 封邮件重新连接一次:26 秒,即 -86%

一部分:创建连接

    Connexion := UTL_SMTP.open_connection(Host, Port);

    UTL_SMTP.AUTH(Connexion,KeyName,KeyValue, 'PLAIN');
    UTL_SMTP.helo(Connexion, Host);

B 部分:发送电子邮件(主循环)

    UTL_SMTP.mail(Connexion, MailFrom_);

    -- Add email
    UTL_SMTP.rcpt(Connexion, EmailAddress);  

    -- Open reader to write data
    UTL_SMTP.open_data(Connexion);

    -- Date
    UTL_SMTP.write_data(Connexion, 'Date: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS') || UTL_TCP.crlf);

    -- Mail to
    UTL_SMTP.write_data(Connexion, 'To: ' || EmailAddress || UTL_TCP.crlf);   

    -- Subject
    UTL_SMTP.write_raw_data(Connexion, utl_raw.cast_to_raw('Subject:' || Subject_));
    UTL_SMTP.WRITE_DATA(Connexion, UTL_TCP.CRLF);      

    -- Message html  
    UTL_SMTP.write_data(Connexion, '--' || l_boundary || UTL_TCP.crlf);
    UTL_SMTP.write_data(Connexion, 'Content-Type: text/html; charset="UTF-8"' || UTL_TCP.crlf || UTL_TCP.crlf);     
    UTL_SMTP.write_raw_data(Connexion, utl_raw.cast_to_raw(MessageInHTML));                    
    UTL_SMTP.write_data(Connexion, UTL_TCP.crlf || UTL_TCP.crlf);  


    UTL_SMTP.write_data(Connexion, '--' || l_boundary || '--' || UTL_TCP.crlf);
    UTL_SMTP.close_data(Connexion);

C部分:关闭连接

    UTL_SMTP.quit(Connexion);