高性能数据库更新(oracle)

时间:2011-04-06 17:51:36

标签: database oracle

我有几个服务在处理不同的输入文件格式(XML,平面文件等)之后将数据转储到数据库(oracle)。我想知道我是否可以让他们生成SQL语句并将它们记录到某个文件系统,并且有一个SQL处理器(类似java hibernet),它将处理这些SQL文件并上传到DB。 执行大量SQL语句(分布在文件系统上,由多个编写器编写)到oracle DB的最快方法是什么?我正在考虑分配数据库和批量更新。但是,我想知道这里的最佳做法。似乎这是一个常见问题,有人必须已经面对/解决了这个问题。 谢谢 Atanu

5 个答案:

答案 0 :(得分:5)

atanu, 最糟糕的事情是生成大量的insert语句。如果您想要速度并且您知道数据的布局,请使用外部表将数据加载到oracle数据库中。这看起来很像使用sql * loader,但您可以使用表访问您的数据。在表定义中,您的数据字段将映射到列名和数据类型。 这将是批量加载到数据库中的最快方法,肯定是。

有关文档,请参阅Managing External Tables

答案 1 :(得分:3)

最佳做法取决于您确定“最佳”的标准。在许多地方,许多地方采用的方法是使用ETL工具,也许是Oracle Warehouse Builder,也许是第三方产品。这不一定是昂贵的产品:Pentaho免费提供水壶"self-supported" community edition

当涉及到自己的滚动时,我认为Hibernate不是最佳选择。特别是如果你主要担心的是表现。我还认为更改您的订阅源以生成SQL语句是一个过于复杂的解决方案。 PL / SQL模块读取文件和本地执行SQ​​L有什么问题?

当我在使用PL / SQL之前做过类似的事情时。诀窍是将输入读取层与数据写入层分开。这是因为文件可能需要大量定制编码,而写入内容通常相当通用(这显然取决于应用程序的精确细节)。

动态元数据驱动架构是一个很有吸引力的概念,特别是如果您的输入结构受到很多变化的影响。然而,这种方法可能难以调试和调整。代码生成是一种替代技术。

在性能方面,尽可能使用批量处理。这是首选PL / SQL而不是具有单独SQL语句的文件的主要原因。 Find out more

答案 2 :(得分:3)

你想要的最后一件事是一堆插入语句......超慢的方法(无论你正在运行多少个进程,相信我)。将所有文件转换为分隔格式,并通过sqlldr对Oracle进行直接加载将是最简单的方法(并且非常快)。

答案 3 :(得分:1)

如果您想获得最高性能,则不需要大量的SQL语句。而是看一下Oracle Data Pump。

不要对平面文件进行任何预处理。而是将它们直接提供给impdp(Oracle Data Pump Importer)。

如果导入数据需要转换,更新等,那么最佳做法是将数据加载到临时表(使用数据泵),在登台表上进行一些预处理,然后将数据合并到生产表中。

数据库外部的预处理通常非常有限,因为您无权访问已加载的数据。因此,您甚至无法检查记录是新记录还是现有记录的更新。

答案 4 :(得分:0)

正如其他人所提到的,如果性能是您唯一关注的问题,您应该考虑一些工具。

但使用纯SQL语句有一些优点。许多组织都有法规,政策和顽固的开发人员阻止任何新工具。一个简单的SQL脚本是数据库的通用语言,它几乎可以在任何地方工作。

如果您决定使用SQL语句,则需要避免使用以下脚本:

insert into my_table values(...);
insert into my_table values(...);
...

并将其替换为单个联合多行的语句:

insert into my_table
select ... from dual union all
select ... from dual union all
...

第二个版本的运行速度要快几倍。

但是,选择合适的尺寸很棘手。大量小插件会浪费大量时间进行通信和其他开销。但是Oracle解析时间以非常大的规模呈指数级增长。根据我的经验,100通常是一个很好的数字。解析变得非常慢一千左右。另外,使用“union all”方法,避免多表插入技巧。由于某些原因,多表插入速度要慢得多,而某些Oracle版本的错误会导致查询在501表中挂起。

(您也可以使用PL / SQL创建一个类似的脚本.1兆字节的PL / SQL过程编译速度比1兆字节的SQL语句解析要快得多。但创建脚本很复杂;集合,动态sql,处理所有类型都正确,创建一个临时对象而不是匿名块,因为大型匿名块导致Diana节点错误等。我已经构建了一个这样的程序,它运行良好,但它可能不值得努力。)