簡體   English   中英

如何提高使用JPA更新數據的性能

[英]How to improve performance of Updating data using JPA

我正在使用EJB和容器管理的EM(對於本地測試,我將在此處創建em)。 我有一個需要根據某些條件更新數據庫的要求,我的問題是Update需要很長時間 ,如何減少它?

我嘗試了兩種方法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));

    }

}

您應該每n次執行一次em.flush()。 例如,如果n-太低,則更多的db交互次數因此會降低執行代碼的速度。 如果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();
          }
    }

檢查OaOnaccount表上的索引,特別要確保p.statusp.documentNumber都有索引,甚至最好使用(status, documentNumber)的組合索引

暫無
暫無

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

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