2014-04-04 57 views
2

我正在研究一個java程序,它實際上從postgresql數據庫中檢索元組,並與他們一起工作。我將每個元組表示爲StringVector以及作爲元組向量的tuple(resultSet)的完整集合。如何高效地處理java中數百萬元組的集合?

Vector<String>   tuple; 
Vector<Vector<String>> resultSet; 

在我的應用程序中,我需要處理幾百萬個元組。這裏是一個簡單的基準,它通過簡單地讀取resultSet中的X元組來模擬我的程序,然後打印結果集大小,第一個和最後一個元組。

基準考慮使用Vector和ArrayList代表元組

List<String>  tuple; 
List<List<String>> resultSet; 

基準程序代碼

import java.util.Vector; 
import java.util.List; 
import java.util.ArrayList; 

public class VectorVSarrayList { 

    public static void loadDataInVector(Integer size){ 

    Vector<Vector<String>> r  = new Vector<Vector<String>>(); 
    Vector<String>   tuple = new Vector<String>(); 

    startTimer(); 

    for(Integer i = 0; i < size; i++){ 

     tuple = new Vector<String>(); 

     for(int j = 0; j < 3; j ++) 
     tuple.add(i.toString() + " tuple "+j); 

     r.add(tuple); 

    } 

    endTimer("vector size " + r.size() + " first element : " + r.get(0).get(0) + ", and  last element : " + r.get(r.size()-1).get(0)); 

    r.clear(); 

    } 

    public static void loadDataInArrayList(Integer size){ 

    List<List<String>> r  = new ArrayList<List<String>>(); 
    List<String>  tuple = new ArrayList<String>(); 


    startTimer();  

    for(Integer i = 0; i < size; i++){ 

     tuple = new ArrayList<String>(); 

     for(int j = 0; j < 3; j ++) 
     tuple.add(i.toString() + " tuple "+j); 

    r.add(tuple); 
    } 

    endTimer("array size " + r.size() + " first element : " + r.get(0).get(0) + ", and last element : " + r.get(r.size()-1).get(0)); 

    r.clear();  
    } 

    public static void main(String [] args){ 

    Integer size = Integer.parseInt(args[0]); 

    loadDataInArrayList(size); 
    loadDataInVector(size); 

    loadDataInArrayList(size); 
    loadDataInVector(size); 
    } 

    private static long startTime = 0; 
    private static long endTime = 0; 

    public static void startTimer(){ 
    startTime = System.currentTimeMillis(); 
    } 

    public static void endTimer(String log){ 
     endTime = System.currentTimeMillis(); 
     System.out.println(log + ", " + (endTime - startTime) + ", ms"); 
} 


} 

我已經運行的基準,以處理1個10百萬元組與Java堆大小擴展到2G,這裏是結果

> time java -Xmx2g VectorVSarrayList 1000000 
array size 1000000 first element : 0 tuple 0, and last element : 999999 tuple 0, 1642, ms 
vector size 1000000 first element : 0 tuple 0, and last element : 999999 tuple 0, 1075, ms 
array size 1000000 first element : 0 tuple 0, and last element : 999999 tuple 0, 1625, ms 
vector size 1000000 first element : 0 tuple 0, and last element : 999999 tuple 0, 308, ms 

real 0m4.829s 
user 0m14.849s 
sys  0m0.500s 


> time java -Xmx2g VectorVSarrayList 10000000 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
    at VectorVSarrayList.loadDataInArrayList(VectorVSarrayList.java:72) 
    at VectorVSarrayList.main(VectorVSarrayList.java:28) 

real 6m12.708s 
user 22m57.662s 
sys  0m6.200s 

這些結果顯示:噸甚至只有10百萬元組,我會花至少6分鐘(僅爲4秒1百萬美元),最終通過內存溢出

OS   : Ubuntu 12.04 
RAM  : 6 GB 
processor : Intel(R) Core(TM) i7-2640M CPU @ 2.80GHz 

運行有什麼好辦法(更好地收集型或更好的初步實踐)來做到這一點什麼樣的工作 ?

+3

要開始,不要使用'Vector';自從Java 1.2以來,它基本上被棄用了。除非使用需要'Vector'的古老API,否則總是比較喜歡'List'。 – chrylis

+4

更一般地說,答案是*不要做*。抓取ResultSet對象並直接遍歷它,而不是嘗試將整個數據庫塞進RAM中。 – chrylis

回答

0

根據「某些工作」的含義,你可以優化這個問題,我理解爲分組來自數據庫的結果。

很顯然,你可以選擇更高效的數據結構,這樣不會讓你的堆溢出。但是,每次數據更改(相關)時,這些都需要維護。在上述情況下,創建初始大小爲3或更好的ArrayList使用LinkedList。

另一種方法是讓數據庫準備數據,以便此準備工作支持您的操作。喜歡你的組鍵排序(數據庫)

  • 排序數據
  • 迭代器雖然數據,只要組密鑰是相同的
  • 當組密鑰的變化做一些填充的矢量處理分組序列(如存儲或打印出第一個,最後一個和大小等)並僅存儲該序列的相關事實。
  • 當數據完成後,在每個序列卓有成效的工作,就像它們聚集

這種方法被稱爲MapReduce的,這裏的映射完成(幾乎)在數據庫和還原在做你的程序。

0

你可以嘗試以下方法:

  1. 做一個元組類每一個字符串變量(或一個ArrayList字符串)
  2. 實現並重寫的hashCode()方法(例如,通過結合元組中每個String的每個hashCode的返回值)
  3. 創建HashMap [10] [10] hashMapArray = ...並在每個具有兩個嵌套for循環的子數組中初始化HashMaps。
  4. 把每一個元組在hashMapArray有:

    int hash = Math.abs(Tuple.hashCode()); 
    HashMap<Integer, Tuple> switchMap = hashMapArray [hash/10][hash % 10]; 
    switchMap.put(Tuple.hashCode(), Tuple); 
    

使用這種方法(或它的變化)可能會加速你的程序相當多。我不得不實施一種快速的分類方法並獲得數以億計的元素,並且持續時間從大約12分鐘下降到幾秒鐘。請不要在將來使用Vector,它會被棄用爲地獄:)

希望這有助於。

相關問題