簡體   English   中英

如何提高從Oracle數據庫獲取大數據的Java應用程序的性能?

[英]how to increase the performance of the java application fetching a large data from oracle database?

我有3個數據庫表-項目,審核和注釋。 我必須從Items表中獲取大量數據,比如說一百萬條記錄,並且對於獲取的每個項目,我都必須從Audits and Comments中獲取數據並將報告寫入分隔的文件中。 所以輸出看起來像

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一百萬次。 我想通過線程提高性能,但是我對線程不熟悉。 那么有人可以幫助我提高性能嗎?

您可以檢索項目,一個聯合查詢以獲取審計,另一個可以獲取注釋。

加快查詢結果速度的一種方法是將選擇行作為單個串聯字符串返回並自行拆分該行。 這通常可以將檢索速度提高2-3倍。 在這方面,較新版本的Oracle可能更聰明,並且開銷較小。

但是,無論如何,您擁有的數據量可能需要一段時間才能從Oracle獲得。

閱讀此資源: http : //www.w3schools.com/Sql/sql_join.asp並使用join。

目前尚不清楚您在做什么,而真正的問題出在提供的有限信息上。

  • 如果要進行一百萬個單個(小型)查詢,則應考慮重組應用程序,以便將其成批合並,或者對整個表進行SELECT。

  • 如果問題是在單個查詢中獲取一百萬行,請考慮使用更復雜的查詢或存儲的查詢,或者使用某些方法在數據庫端進行一些數據減少。

您可以編寫一個存儲過程,該過程將輸出帶有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;

最好將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

我的想法是運行三個查詢(一個返回所有項目,一個返回所有注釋,一個返回所有審計條目),每個查詢按項目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代碼快得多。

如BazzPsychoNut所述,在管理UNION / JOIN之后,如果ResultSet大,則將FetchSize值調整為更大的值可能會有所幫助。 Oracle的默認值為10。

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

請參閱檢索大型ResultSet

如果您的系統(硬件,配置等)的大小能夠處理放入其中的數據量,則最好,最快和最簡單的方法是簡單地將表聯接到一個查詢中,獲取行(請參閱有關fetch_size的其他注釋),然后然后以您想要的任何格式轉儲它。

從示例輸出格式來看,您需要按排序順序(項目,審核,注釋)處理行。 您將遍歷各行並跟蹤最后處理的項目,並且只要當前ITEM_ID與上一個項目不同,就輸出項目數據。

在決定如何實現此功能時,您要考慮的最重要的方面是聯接和排序是否適合內存。 如果排序/聯接溢出到磁盤,則必須解決該問題才能獲得所需的性能。 有關如何避免磁盤溢出的一些示例:

將表(或它們的副本)散列在ITEM_ID上。 然后,您可以按分區對表進行聯接,以使每個聯接都適合內存。

或者,您可以從所有表中獲取所有數據,然后在Java代碼中,將項目放入鏈接列表,並將審計/評論放入由item_no鍵控的某些基於哈希的結構中。 然后,您將遍歷項目,並按item_id查詢審核/注釋。 該解決方案避免了排序操作,並且不需要將聯接的結果放入內存中。

或者,您可以實現一些自己動手的分區。 例如,查詢數據9次。 在第一個查詢中,您僅獲取以ITEM_ID開頭或結尾為1的項。第二個查詢對所有以2 etcetera開頭/結尾的項進行查找。 此解決方案導致對所有表進行9次表掃描,這顯然不是很有效。 但是,如果可以避免溢出到磁盤上,實際上可能會更快。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM