如何加快通过 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);
我正在通过 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);