我有一个邪恶的问题。在Oracle 10中,有一对视图和桌子一遍又一遍地完成类似的事情:
proc_log('DELETE 1');
DELETE FROM table_1;
proc_log('INSERT 1');
INSERT INTO table_1 SELECT * FROM view_1;
proc_log('FINISH 1');
and view/表2和表2和3和4和5 ...以及36。
我想做这样的事情:
PROCEDURE proc_import(p_table VARCHAR2) IS
BEGIN
proc_log('DELETE ' || p_table);
EXECUTE IMMEDIATE 'DELETE FROM table_' || p_table;
proc_log('INSERT ' || p_table);
EXECUTE IMMEDIATE 'INSERT INTO table_' || p_table || ' SELECT * FROM view_' || p_table;
proc_log('FINISH || p_table);
COMMIT;
END;
然后调用所有36对函数。
毫不奇怪,这些东西比硬编码慢50%。
我的问题:有人对如何更快地提出了想法。甚至更好,我该如何使这些东西与众不同,但类似优雅?
编辑
整个内容都是这样构建的:
CREATE OR REPLACE PACKAGE PKG_IMPORT IS PROCEDURE proc_log IS BEGIN [funky not important stuff] END; PROCEDURE proc_import IS BEGIN proc_import_table('1', TRUE); proc_import_table('2'); proc_import_table('3'); proc_import_table('4', TRUE); proc_import_table('5'); ... proc_import_table('36'); END; PROCEDURE proc_import(p_table VARCHAR2, p_whole BOOLEAN DEFAULT FALSE) IS BEGIN proc_log('DELETE ' || p_table); IF p_whole THEN EXECUTE IMMEDIATE 'DELETE FROM table_' || p_table; ELSE EXECUTE IMMEDIATE 'DELETE FROM table_' || p_table || ' WHERE business_logic_applies'; END IF; proc_log('INSERT ' || p_table); EXECUTE IMMEDIATE 'INSERT INTO table_' || p_table || ' SELECT * FROM view_' || p_table; proc_log('FINISH || p_table); COMMIT; END; END PKG_IMPORT;
该过程proc_import每晚一次由工作调用。所有proc_import_table呼叫都硬编码的原因是,某些表需要其他导入信息。
恐怕我无法在此处复制/粘贴原始代码,因为我不知道我是否可以这样做。希望这会有所帮助...
首先,如果您没有任何条件要删除,则可以截断表。
TRUNCATE TABLE table_1;
TRUNCATE
是DDL操作,它不会删除行,而只能操纵高水位,从而使操作非常快。,但也要牢记无法回滚,因为它是DDL。
另一方面,您可以执行直接路径插入,而不是常规路径。尝试以下操作:
INSERT /*+ append */ into table_1 select * from view_1;
这将导致Oracle直接在高水印上方写数据,从而使操作更快。如果您的表为PARALLEL
。
原始代码将更快地执行,因为Oracle将能够预先编译查询,而该查询无法与'execute time toctimate'进行。
您的新代码看起来更简洁,但实际上更难阅读。至少,您应该给出完整表名的名称,否则任何其他人都必须查看您的代码的名称。
也就是说,我想我希望看到36个删除和36个插入陈述 - 少少了且更加清晰。如果较短的Procs帮助,您可以将所有这些陈述放在其自己的Proc中。