如何提高使用 JPA 更新数据的性能
How to improve performance of Updating data using JPA
我正在使用 EJB 和容器管理的 EM(为了进行本地测试,我在这里创建了 em)。
我有一个需要根据某些条件更新数据库的要求,我的问题是 更新需要很长时间,如何减少它?
我尝试了两种方法
1>更新查询
2> 实体更新
如果我做错了什么,或者存在任何其他方法,请告诉我。
注意:更新代码如下
public class Test {
private static final int OaOnaccount = 0;
private static final int ArrayList = 0;
private static EntityManagerFactory emf;
private static EntityManager em;
static int TEST_SIZE = 20000/4;
public static void main(String[] args) {
// createBulk();
createUpdateQuery();
// update();
}
private static void createUpdateQuery() {
long st = System.currentTimeMillis();
emf = Persistence.createEntityManagerFactory("Jpa");
em = emf.createEntityManager();
System.out.println("---- createUpdateQuery ---");
EntityTransaction tx = em.getTransaction();
Query query = em.createQuery("SELECT p FROM OaOnaccount p");
tx.begin();
java.util.Vector<OaOnaccount> list = (java.util.Vector<OaOnaccount>) query.getResultList();
for (int i = 0; i < list.size(); i++) {
String m = 1000000 + (i / 20) + "";
query = em
.createQuery("UPDATE OaOnaccount p SET p.status='COMPLETED', p.billingDoc='12112ABCS' WHERE p.crDrIndicator='H' AND p.status ='OPEN' AND p.documentNumber="+ m);
query.executeUpdate();
}
em.flush();
tx.commit();
long et = System.currentTimeMillis();
System.out.println("Test.createUpdateQuery() Time " + (et - st));
}
private static void update() {
long st = System.currentTimeMillis();
emf = Persistence.createEntityManagerFactory("Jpa");
em = emf.createEntityManager();
System.out.println("---- update ---");
EntityTransaction tx = em.getTransaction();
Query query = em.createQuery("SELECT p FROM OaOnaccount p");
tx.begin();
java.util.Vector<OaOnaccount> list = (java.util.Vector<OaOnaccount>) query
.getResultList();
for (int i = 0; i < list.size(); i++) {
String m = 1000000 + (i / 20) + "";
query = em
.createQuery("SELECT p FROM OaOnaccount p WHERE p.crDrIndicator='H' AND p.status ='OPEN' AND p.documentNumber="
+ m);
java.util.Vector<OaOnaccount> listEn = (java.util.Vector<OaOnaccount>) query
.getResultList();
for (int j = 0; j < listEn.size(); j++) {
listEn.get(j).setBillingDoc("12112ABCS");
listEn.get(j).setStatus("COMPLETED");
}
}
em.flush();
tx.commit();
long et = System.currentTimeMillis();
System.out.println("Test.Update() Time " + (et - st));
}
public static void createBulk() {
long st = System.currentTimeMillis();
emf = Persistence.createEntityManagerFactory("Jpa");
em = emf.createEntityManager();
System.out.println("-------");
EntityTransaction tx = em.getTransaction();
tx.begin();
for (int i = 0; i < TEST_SIZE; i++) {
OaOnaccount entity = new OaOnaccount();
entity.setId("ID-" + i);
entity.setCrDrIndicator(i % 2 == 0 ? "H" : "S");
entity.setDocumentNumber(1000000 + (i / 20) + "");
entity.setAssignment(89000000 + (i / 27) + "");
entity.setStatus("OPEN");
em.persist(entity);
}
em.flush();
tx.commit();
long et = System.currentTimeMillis();
System.out.println("Test.createBulk() Time " + (et - st));
}
}
检查您在 OaOnaccount table 上的索引,特别确保 p.status
和 p.documentNumber
上有索引,或者更好的是使用 [=12 的组合索引=]
您应该对每 n 次迭代执行 em.flush()。例如,如果 n- 数据库交互的数量太少,则执行代码的速度会变慢。如果 n- 太高,内存中驻留的对象太多,因此交换次数越多,代码执行速度越慢。请适度选择n值并应用。我尝试更新 240 万条记录,我遇到了同样的问题。
for (int i = 0; i < list.size(); i++) {
String m = 1000000 + (i / 20) + "";
query = em
.createQuery("UPDATE OaOnaccount p SET p.status='COMPLETED', p.billingDoc='12112ABCS' WHERE p.crDrIndicator='H' AND p.status ='OPEN' AND p.documentNumber="+ m);
query.executeUpdate();
if(i%100==0){// 100 to just to show example-- % operation is costly. you can use better logic to flush. frequent flushing is necessary
em.flush();
}
}
我正在使用 EJB 和容器管理的 EM(为了进行本地测试,我在这里创建了 em)。 我有一个需要根据某些条件更新数据库的要求,我的问题是 更新需要很长时间,如何减少它?
我尝试了两种方法 1>更新查询 2> 实体更新
如果我做错了什么,或者存在任何其他方法,请告诉我。
注意:更新代码如下
public class Test {
private static final int OaOnaccount = 0;
private static final int ArrayList = 0;
private static EntityManagerFactory emf;
private static EntityManager em;
static int TEST_SIZE = 20000/4;
public static void main(String[] args) {
// createBulk();
createUpdateQuery();
// update();
}
private static void createUpdateQuery() {
long st = System.currentTimeMillis();
emf = Persistence.createEntityManagerFactory("Jpa");
em = emf.createEntityManager();
System.out.println("---- createUpdateQuery ---");
EntityTransaction tx = em.getTransaction();
Query query = em.createQuery("SELECT p FROM OaOnaccount p");
tx.begin();
java.util.Vector<OaOnaccount> list = (java.util.Vector<OaOnaccount>) query.getResultList();
for (int i = 0; i < list.size(); i++) {
String m = 1000000 + (i / 20) + "";
query = em
.createQuery("UPDATE OaOnaccount p SET p.status='COMPLETED', p.billingDoc='12112ABCS' WHERE p.crDrIndicator='H' AND p.status ='OPEN' AND p.documentNumber="+ m);
query.executeUpdate();
}
em.flush();
tx.commit();
long et = System.currentTimeMillis();
System.out.println("Test.createUpdateQuery() Time " + (et - st));
}
private static void update() {
long st = System.currentTimeMillis();
emf = Persistence.createEntityManagerFactory("Jpa");
em = emf.createEntityManager();
System.out.println("---- update ---");
EntityTransaction tx = em.getTransaction();
Query query = em.createQuery("SELECT p FROM OaOnaccount p");
tx.begin();
java.util.Vector<OaOnaccount> list = (java.util.Vector<OaOnaccount>) query
.getResultList();
for (int i = 0; i < list.size(); i++) {
String m = 1000000 + (i / 20) + "";
query = em
.createQuery("SELECT p FROM OaOnaccount p WHERE p.crDrIndicator='H' AND p.status ='OPEN' AND p.documentNumber="
+ m);
java.util.Vector<OaOnaccount> listEn = (java.util.Vector<OaOnaccount>) query
.getResultList();
for (int j = 0; j < listEn.size(); j++) {
listEn.get(j).setBillingDoc("12112ABCS");
listEn.get(j).setStatus("COMPLETED");
}
}
em.flush();
tx.commit();
long et = System.currentTimeMillis();
System.out.println("Test.Update() Time " + (et - st));
}
public static void createBulk() {
long st = System.currentTimeMillis();
emf = Persistence.createEntityManagerFactory("Jpa");
em = emf.createEntityManager();
System.out.println("-------");
EntityTransaction tx = em.getTransaction();
tx.begin();
for (int i = 0; i < TEST_SIZE; i++) {
OaOnaccount entity = new OaOnaccount();
entity.setId("ID-" + i);
entity.setCrDrIndicator(i % 2 == 0 ? "H" : "S");
entity.setDocumentNumber(1000000 + (i / 20) + "");
entity.setAssignment(89000000 + (i / 27) + "");
entity.setStatus("OPEN");
em.persist(entity);
}
em.flush();
tx.commit();
long et = System.currentTimeMillis();
System.out.println("Test.createBulk() Time " + (et - st));
}
}
检查您在 OaOnaccount table 上的索引,特别确保 p.status
和 p.documentNumber
上有索引,或者更好的是使用 [=12 的组合索引=]
您应该对每 n 次迭代执行 em.flush()。例如,如果 n- 数据库交互的数量太少,则执行代码的速度会变慢。如果 n- 太高,内存中驻留的对象太多,因此交换次数越多,代码执行速度越慢。请适度选择n值并应用。我尝试更新 240 万条记录,我遇到了同样的问题。
for (int i = 0; i < list.size(); i++) {
String m = 1000000 + (i / 20) + "";
query = em
.createQuery("UPDATE OaOnaccount p SET p.status='COMPLETED', p.billingDoc='12112ABCS' WHERE p.crDrIndicator='H' AND p.status ='OPEN' AND p.documentNumber="+ m);
query.executeUpdate();
if(i%100==0){// 100 to just to show example-- % operation is costly. you can use better logic to flush. frequent flushing is necessary
em.flush();
}
}