Oracle 数据过滤性能:sqlldr+触发器还是sqlldr+存储过程?
我必须在我的数据库中加载数百万条记录,这些记录需要根据它们的某些列值进行进一步处理。特别是,如果一行满足一个条件,我将该行保存在表B中,否则我将其保存在表C中 根据文档,使用直接路径的sqlldr非常快,无论如何,加载这样的行不会触发触发器。因此,我提出了两个解决方案: 解决方案1: 使用直接路径为true的sql loader加载表A中的所有数据。然后调用存储过程执行实际筛选。我对此不太确定,但在本例中,oracle似乎在幕后执行多线程处理 解决方案2: 使用sql loader with DIRECT PATH=false并在表A上插入后激活触发器。在这种情况下,为了性能起见,我需要将数据文件拆分为多个文件并多次调用sql loader来明确执行多线程处理,我不知道如何在bash脚本上执行该操作Oracle 数据过滤性能:sqlldr+触发器还是sqlldr+存储过程?,oracle,sql-loader,Oracle,Sql Loader,我必须在我的数据库中加载数百万条记录,这些记录需要根据它们的某些列值进行进一步处理。特别是,如果一行满足一个条件,我将该行保存在表B中,否则我将其保存在表C中 根据文档,使用直接路径的sqlldr非常快,无论如何,加载这样的行不会触发触发器。因此,我提出了两个解决方案: 解决方案1: 使用直接路径为true的sql loader加载表A中的所有数据。然后调用存储过程执行实际筛选。我对此不太确定,但在本例中,oracle似乎在幕后执行多线程处理 解决方案2: 使用sql loader with D
哪一种会带来更好的性能?两者之间的性能差异有多大?了解性能的唯一方法就是实际尝试不同的方法。对于第一个选项,您可以尝试直接SQL,而不是使用可能导致逐行处理的过程。看见这允许您指定一个条件以将插入指向不同的表 编辑 我自己从来没有写过多表插入,所以我想我应该试试。它很整洁
> 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
在加载数据的情况下,在添加到核心数据之前需要进行处理/清理,我强烈建议首先将其加载到暂存表中,并使用可用的最快方法,即带有直接路径的sqlldr。这样就可以快速完成数据加载并清除灰尘。关于日志记录和恢复,直接路径会带来一些影响,因此最好将该活动保持在一个尽可能小的窗口内 然后,可以使用存储过程更灵活地处理暂存数据。在这里,您可以将记录拆分为多个批次,并让存储过程通过参数处理特定批次,然后让多个存储过程在离散批次上并行运行,假设每个记录都可以离散处理。添加诸如流程状态就绪、检查、失败、完成等内容来控制流程,您就拥有了一些灵活且更易于管理的功能。在我做的上一个项目中,我们从文件中加载了1亿行,然后在安静的批处理期间,在几个晚上分批处理它们
从编码角度看,这可能需要更多的工作,但通过sqlldr处理文件和坏记录、重新加载和避免重复比作为表数据更麻烦。我不太喜欢pl/sql,但是否可以在insert all语句之后立即为每个循环插入一个?显然,我不想手动编写数百万个插入:我添加了一个示例。您应该很好地回答一点OT:直接路径禁用索引和自动增量触发器。。。我确实有索引和一个不可为空的ID列。如何处理这个问题?正如我所说的,将它加载到一个暂存区域,这些可以是没有索引/约束的新表,然后处理到主数据表中。您可以禁用索引,然后重新生成它们,但这是一种平衡行为,具体取决于在处理过程中是否必须从禁用的索引表中读取。正如daivrz所说,我们所能做的就是提供一般性的建议,你所决定的实际过程取决于你的实验。