数据过滤performance:sqlldr+触发器还是sqlldr+存储过程?
Data filtering performance:sqlldr+triggers or sqlldr+stored procedure?
我必须在我的数据库中加载数百万条记录,说记录需要根据它们的某些列值进行进一步处理。特别是如果一行满足条件,我将该行保存在 table B 中,否则我将其保存在 table C 中。
根据文档 sqlldr 使用 DIRECT PATH 非常快,无论如何加载这样的行不会触发触发器。所以,我想出了两个解决方案:
解决方案 1:
使用带有 DIRECT PATH=true 的 sql 加载器加载 table A 中的所有数据。然后调用存储过程来执行实际的过滤。我不太确定,但在这种情况下,oracle 似乎实际上在幕后执行多线程。
解决方案 2:
使用带 DIRECT PATH=false 的 sql 加载程序,在 table A.in 上插入后激活触发器,在这种情况下,为了性能起见,我需要通过拆分我的多个文件中的数据文件并多次调用 sql 加载程序(顺便说一句,我不知道如何在 bash 脚本上执行此操作...)
哪一个性能更好?两者之间有那么大的性能差异吗?
了解性能的唯一方法是实际尝试不同的方法。对于第一个选项,您可以直接尝试 SQL,而不是使用过程(这可能会导致逐行处理)。参见 multi table inserts。这允许您指定条件以将插入定向到不同的 tables.
编辑
我从来没有真正写过一个多 table 插入自己所以我想我会尝试。挺好看的。
> CREATE TABLE t_stg
(pk NUMBER PRIMARY KEY
,cond NUMBER
,text VARCHAR2(20))
table T_STG created.
> CREATE TABLE t_1 AS SELECT * FROM t_stg WHERE 1=2
table T_1 created.
> CREATE TABLE t_2 AS SELECT * FROM t_stg where 1=2
table T_2 created.
> INSERT INTO t_stg
(SELECT LEVEL lvl
,mod(LEVEL, 2) cond
,to_char(SYSDATE + LEVEL, 'Day') txt
FROM dual
CONNECT BY LEVEL < 8)
7 rows inserted.
> SELECT *
FROM t_stg
PK COND TEXT
---------- ---------- --------------------
1 1 Sunday
2 0 Monday
3 1 Tuesday
4 0 Wednesday
5 1 Thursday
6 0 Friday
7 1 Saturday
7 rows selected
> INSERT ALL
WHEN cond = 1 THEN
INTO t_1 (pk, cond, text) VALUES (pk*2, cond, text)
ELSE
INTO t_2 (pk, cond, text) VALUES (pk, cond, text)
SELECT pk
,cond
,text
FROM t_stg
7 rows inserted.
> SELECT *
FROM t_1
PK COND TEXT
---------- ---------- --------------------
2 1 Sunday
6 1 Tuesday
10 1 Thursday
14 1 Saturday
> SELECT *
FROM t_2
PK COND TEXT
---------- ---------- --------------------
2 0 Monday
4 0 Wednesday
6 0 Friday
在加载数据然后需要 processing/cleansing 添加到核心数据的情况下,我的强烈偏好是先将其加载到分段 table,并使用最快的可用方法,即 sqlldr直接路径。这样可以快速完成数据加载和清理。直接路径对日志记录和恢复有影响,因此最好将 activity 保持在尽可能小的 window 范围内。
然后可以使用存储过程更灵活地处理暂存数据。在这里,您可以将记录分成批次,并让存储过程通过参数处理特定的批次,然后在离散批次上并行处理超过 1 个存储过程 运行(假设每个记录都可以离散处理)。添加诸如流程状态(就绪、正在检查、失败、已完成)之类的内容来控制流程,您就拥有了一些灵活且更易于管理的东西。在我做的最后一个项目中,我们从文件中加载了 1 亿行,然后在安静的批处理期间用几个晚上的时间分批处理它们。
明智的编码可能需要更多工作,但通过 sqlldr 处理文件和错误记录并重新加载和避免重复比 table 数据更麻烦。
我必须在我的数据库中加载数百万条记录,说记录需要根据它们的某些列值进行进一步处理。特别是如果一行满足条件,我将该行保存在 table B 中,否则我将其保存在 table C 中。
根据文档 sqlldr 使用 DIRECT PATH 非常快,无论如何加载这样的行不会触发触发器。所以,我想出了两个解决方案:
解决方案 1:
使用带有 DIRECT PATH=true 的 sql 加载器加载 table A 中的所有数据。然后调用存储过程来执行实际的过滤。我不太确定,但在这种情况下,oracle 似乎实际上在幕后执行多线程。
解决方案 2:
使用带 DIRECT PATH=false 的 sql 加载程序,在 table A.in 上插入后激活触发器,在这种情况下,为了性能起见,我需要通过拆分我的多个文件中的数据文件并多次调用 sql 加载程序(顺便说一句,我不知道如何在 bash 脚本上执行此操作...)
哪一个性能更好?两者之间有那么大的性能差异吗?
了解性能的唯一方法是实际尝试不同的方法。对于第一个选项,您可以直接尝试 SQL,而不是使用过程(这可能会导致逐行处理)。参见 multi table inserts。这允许您指定条件以将插入定向到不同的 tables.
编辑
我从来没有真正写过一个多 table 插入自己所以我想我会尝试。挺好看的。
> CREATE TABLE t_stg
(pk NUMBER PRIMARY KEY
,cond NUMBER
,text VARCHAR2(20))
table T_STG created.
> CREATE TABLE t_1 AS SELECT * FROM t_stg WHERE 1=2
table T_1 created.
> CREATE TABLE t_2 AS SELECT * FROM t_stg where 1=2
table T_2 created.
> INSERT INTO t_stg
(SELECT LEVEL lvl
,mod(LEVEL, 2) cond
,to_char(SYSDATE + LEVEL, 'Day') txt
FROM dual
CONNECT BY LEVEL < 8)
7 rows inserted.
> SELECT *
FROM t_stg
PK COND TEXT
---------- ---------- --------------------
1 1 Sunday
2 0 Monday
3 1 Tuesday
4 0 Wednesday
5 1 Thursday
6 0 Friday
7 1 Saturday
7 rows selected
> INSERT ALL
WHEN cond = 1 THEN
INTO t_1 (pk, cond, text) VALUES (pk*2, cond, text)
ELSE
INTO t_2 (pk, cond, text) VALUES (pk, cond, text)
SELECT pk
,cond
,text
FROM t_stg
7 rows inserted.
> SELECT *
FROM t_1
PK COND TEXT
---------- ---------- --------------------
2 1 Sunday
6 1 Tuesday
10 1 Thursday
14 1 Saturday
> SELECT *
FROM t_2
PK COND TEXT
---------- ---------- --------------------
2 0 Monday
4 0 Wednesday
6 0 Friday
在加载数据然后需要 processing/cleansing 添加到核心数据的情况下,我的强烈偏好是先将其加载到分段 table,并使用最快的可用方法,即 sqlldr直接路径。这样可以快速完成数据加载和清理。直接路径对日志记录和恢复有影响,因此最好将 activity 保持在尽可能小的 window 范围内。
然后可以使用存储过程更灵活地处理暂存数据。在这里,您可以将记录分成批次,并让存储过程通过参数处理特定的批次,然后在离散批次上并行处理超过 1 个存储过程 运行(假设每个记录都可以离散处理)。添加诸如流程状态(就绪、正在检查、失败、已完成)之类的内容来控制流程,您就拥有了一些灵活且更易于管理的东西。在我做的最后一个项目中,我们从文件中加载了 1 亿行,然后在安静的批处理期间用几个晚上的时间分批处理它们。
明智的编码可能需要更多工作,但通过 sqlldr 处理文件和错误记录并重新加载和避免重复比 table 数据更麻烦。