我正在研究一个java程序,它实际上从postgresql数据库中检索元组并使用它们进行一些工作。我将每个元组表示为Vector
的{{1}}和完整的元组(resultSet)作为元组的向量。
String
在我的应用程序中,我需要处理数百万个元组。这是一个简单的基准测试,它通过简单地读取resultSet中的X元组然后打印resultSet Size,第一个和最后一个元组来模拟我的程序。
基准测试考虑使用vector和arrayList来表示元组
Vector<String> tuple;
Vector<Vector<String>> resultSet;
基准程序代码
List<String> tuple;
List<List<String>> resultSet;
我运行基准测试来处理1千万个元组,java堆大小扩展到2G,这里是结果
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");
}
}
这些结果表明,即使只有1000万个元组,我将花费至少6分钟(而1百万分之4秒)并最终通过OutOfMemory
> 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
有没有一种好方法(更好的收集类型或更好的实践)来完成这类工作?
答案 0 :(得分:0)
取决于“某些工作”的含义,您可以优化我理解为分组数据库结果的问题。
显然,您可以选择更高效的数据结构,这不会过度堆积您的堆。但是每次数据发生变化(相关)时都需要维护。在上面的例子中,使用LinkedList创建初始大小为3或更高的ArrayList。
另一种方法是让数据库准备数据,以便此准备工作支持您的操作。喜欢
这种方法称为MapReduce,这里的映射在数据库中完成(虚拟),并在程序中完成。
答案 1 :(得分:0)
您可以尝试以下方法:
将每个元组放在hashMapArray中:
int hash = Math.abs(Tuple.hashCode());
HashMap<Integer, Tuple> switchMap = hashMapArray [hash / 10][hash % 10];
switchMap.put(Tuple.hashCode(), Tuple);
使用这种方法(或其变体)可能会大大加快你的程序。我必须实现一种快速的排序方式,并获得数以亿计的元素,并且持续时间从大约12分钟到几秒钟。并且请将来不要使用Vector,它已被弃用:)
希望这有帮助。