如何提高java应用程序从oracle数据库中获取大数据的性能?

时间:2010-12-02 12:11:56

标签: java multithreading performance oracle

我有3个数据库表 - 项目,审计和评论。我必须从 Items 表中获取大量数据,比如100万条记录,对于每个提取的项目,我必须从审核中检索数据注释并将报告写入分隔文件。所以输出可能看起来像,

Item entry 1
    Audit entry 1 for Item 1
    Audit entry 2 for Item 1
    Audit entry 3 for Item 1
    Comment entry 1 for Item 1
    Comment entry 2 for Item 1
Item entry 2 
    Audit entry 1 for Item 2
    .
    .
    .

现在这需要花费很多时间,因为该程序正在为每个查询oracle 100万次。我想通过线程增加性能,但我不熟悉线程。那么有人可以帮助我提高性能吗?

8 个答案:

答案 0 :(得分:3)

您可以检索项目,获取审核的联合查询以及获取评论的其他查询。

加速查询结果的一种方法是将选择行作为单个连接字符串返回并自行拆分该行。这用于加快检索速度2-3倍。在这方面,较新版本的Oracle可能更加智能,并且开销较小。

然而,在任何情况下,您拥有此数据的数量可能需要一段时间才能从Oracle获得。

答案 1 :(得分:2)

阅读此资源:http://www.w3schools.com/Sql/sql_join.asp并使用加入。

答案 2 :(得分:1)

目前还不清楚你在做什么,以及你提供的有限信息中你真正的问题是什么。

  • 如果您正在进行一百万个(小)查询,您应该考虑重组您的应用程序,以便将它们分批组合,或者在整个表格中进行SELECT。

  • 如果问题是在单个查询中提取了一百万行,那么请考虑使用更复杂的查询或存储的查询,或者在数据库端进行一些数据缩减。

答案 3 :(得分:1)

您可以编写一个存储过程,该过程将使用utl_file包输出该文件,并从java调用该文件。这样你就可以使用像

这样的东西
f := utl_file.fopen('my_dir','my_file','w');
FOR r_items IN (SELECT * FROM items) LOOP
  utl_file.put_line(f,r_items.name);

  FOR r_audit IN (SELECT * FROM audit WHERE item_id = r_items.id) LOOP
    utl_file.put_line(f,r_audit.some_field);
  END LOOP;

  FOR r_comments IN (SELECT * FROM comments WHERE item_id = r_items.id) LOOP
    utl_file.put_line(f,r_comments.some_field);
  END LOOP;
END LOOP;

答案 4 :(得分:0)

可能最好将UNION与JOIN结合起来以最佳方式获取所有数据。 查询可能如下所示:

select itm.itemid
,      tmp.what || ' ' || tmp.entry || ' for Item ' || tmp.itemid line
from   items itm
join
(
    select itemid
    ,      entry 
    ,      'Audit' what
    from   audits
    union all
    select itemid
    ,      entry 
    ,      'Comment' what
    from   comments
) tmp on itm.itemid = tmp.itemid

答案 5 :(得分:0)

我的想法是运行三个查询(一个用于返回所有项目,一个用于所有注释,一个用于所有审核条目)每个查询按项目ID排序

SELECT * FROM
  (SELECT itemid, 1 type, null seq, item_line line
   from items
   union all
   select itemid, 2, audit_seq, audit_line
   from audit
   union all
   select itemid, 3, comment_seq comment_line 
   from comments)
order by itemid, type, seq

这意味着将所有逻辑构建到数据库中的行条目,但它可能比java代码运行得快得多。

答案 6 :(得分:0)

在管理你的UNION / JOIN之后,如BazzPsychoNut所说,如果ResultSet很大,将FetchSize值调整为更大的值可能会有所帮助。 Oracle的默认值为10.

Statement stmt = conn.createStatement();
stmt.setFetchSize(200);
ResultSet rset = stmt.executeQuery(sql);

请参阅Retrieve large ResultSet

答案 7 :(得分:0)

如果您的系统(硬件,配置等)的大小可以处理您放入其中的数据量,那么最好,最快速和最简单的方法是在一个查询中简单地连接表,获取行(请参阅其他有关的行fetch_size)然后以任何你想要的格式转储它。

从示例输出格式判断,您需要按排序顺序(项目,审计,注释)处理行。您将迭代行并跟踪最后处理的项目,并且只要当前ITEM_ID与上一项不同,您就会输出项目数据。

当您决定如何实现这一点时,您要考虑的最重要的一个方面是连接和排序是否适合内存。如果排序/连接溢出到磁盘,则必须解决此问题才能实现所需的性能。有关如何避免磁盘溢出的一些示例:

对ITEM_ID上的表(或其副本)进行哈希分区。然后,您可以分区连接表,以便每个连接都适合内存。

或者您可以从所有表中获取所有数据,并在您的Java代码中,将项目放在链接列表中,并将审计/注释放在由item_no键入的某些基于散列的结构中。然后,您将遍历项目并通过item_id查询审计/注释。此解决方案避免了排序操作,并且不需要将连接结果放入内存中。

或者您可以实现一些自己动手的分区。例如,查询数据9次。在第一个查询中,您只获取ITEM_ID以1开头或结尾的项目。第二个查询将以2等等开始/结束所有项目。该解决方案导致所有表上的9个表扫描,这显然不是非常有效。但是,如果你可以避免溢出到磁盘,它可能实际上更快。