class Person {
public int number;
public String name;
}
class Cannon extends Thread {
private Collection<Person> people;
private int COUNT = 5000;
public Cannon(Collection<Person> input) {
people = input;
}
public void run() {
try {
var db = DriverManager.getConnection("jdbc:postgresql://localhost/postgres", "postgres", "test");
var builder = new StringBuilder();
builder.append("insert into person (name, number) values (?,?)");
for (int i = 1; i < COUNT; i++) {
builder.append(",(?,?)");
}
var s = db.prepareStatement(builder.toString());
int i = 0;
for (Person p : people) {
s.setString(2 * i + 1, p.name);
s.setInt(2 * i + 2, p.number);
i++;
if (i == COUNT) {
s.executeUpdate();
i = 0;
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public class Main {
static public void main(String[] args) throws InterruptedException {
var data = new ArrayList<Person>();
var r = new Random();
for (int i = 0; i < 10000000; i++) {
var p = new Person();
p.name = String.valueOf(r.nextInt());
p.number = r.nextInt();
data.add(p);
}
var threads = new Thread[4];
for (int i = 0; i < threads.length; i++) {
var chunk = new ArrayList<Person>();
for (int j = 0; j < data.size() / threads.length; j++) {
int index = (data.size() / threads.length) * i + j;
chunk.add(data.get(index));
}
threads[i] = new Cannon(chunk);
}
long start = System.currentTimeMillis();
for (int i = 0; i < threads.length; i++) threads[i].start();
for (int i = 0; i < threads.length; i++) threads[i].join();
System.out.println(System.currentTimeMillis() - start);
}
}
3条答案
按热度按时间46qrfjad1#
saveall()方法会更快。saveall还遍历列表并调用save方法,因此我们可能认为性能必须相似。但是@transactional的默认传播类型是必需的,因此如果没有提供,每次都会创建一个新的事务。在saveall中只有一个事务,但在save中它将等于列表的大小。因此两者之间的性能差距。
t8e9dugd2#
受你问题的启发,我做了一个小实验。它能在10秒内把10万张唱片放到我的机器上。如果你想的话,你可以使用代码。
ubby3x7f3#
对spring存储库的每次调用通常以对数据库的一次调用结束。即使数据库运行在同一台主机上,它仍然是一个昂贵的操作(相对于在jvm中调用函数)。
这么叫
repository.saveAll(list)
将在一次对数据库的调用中结束list.parallelStream().foreach(e -> repository.save(e))
将在对列表中的每个项目的数据库调用中结束。即使您的数据库可以同时处理多个请求,它仍然受限于主机的资源,并且可能受到dbms的同步机制的限制。换句话说,数据库一次也只能处理这么多请求。
此外,您不想在一次通话中保存250万个条目。这可能会导致outofmemoryexceptions。