我有一个邪恶的问题。在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');
与View / Table 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调用都是硬编码的原因是某些表需要额外的导入信息。
我担心我不能在这里复制/粘贴原始代码,因为我不知道我是否被允许这样做。希望这会有所帮助...
答案 0 :(得分:2)
首先,如果您没有关于要删除哪些行的任何条件,则可以截断该表。
TRUNCATE TABLE table_1;
TRUNCATE
是一个ddl操作,它不会删除行,它只会操纵高水位线,使操作非常快。 但请记住它无法回滚,因为它是DDL。
另一方面,您可以执行直接路径插入,而不是常规路径插入。试试这个:
INSERT /*+ append */ into table_1 select * from view_1;
这将导致Oracle将数据直接写在高水印之上,从而使操作更快。如果您的表格为PARALLEL
,它也可能可能。
答案 1 :(得分:0)
原始代码可以更快地执行,因为Oracle可以预编译查询,而“执行立即”则无法执行。
您的新代码可能看起来更简洁,但实际上更难阅读。至少,不是传递一个表号,你应该给出完整的表名,否则任何看你的代码的人都必须修改数字的含义。
那就是说,我想我更愿意看到36个删除和36个插入语句 - 远没有那么神秘和更加整洁。如果它有助于缩短过程,你可以将所有这些陈述放入自己的过程中。