2014-10-17 7 views
5

मैं ग्रहण लिंक का उपयोग करके अपने जेपीए कार्यान्वयन को अनुकूलित करने की कोशिश कर रहा हूं। मैंने बैच ऑपरेशंस को इसमें जोड़ा है। लेकिन यह अभी भी 50 000 आवेषण करने के लिए बहुत समय ले रहा है। जेडीबीसी के साथ कच्चे एसक्यूएल का उपयोग करके सटीक उसी डालने में लगने वाले समय में 10 गुना अधिक समय लगता है।EclipseLink बैच बहुत धीमी गति से

यह सुनिश्चित करने के लिए कि बैच ऑपरेशंस वास्तव में काम कर रहे थे, मैंने अपने पैकेट की जांच करने के लिए वायरशर्क का उपयोग किया और यह बैच आवेषण का उपयोग नहीं कर रहा है।

enter image description here

यह नहीं कर रहा है:

यहाँ डालने के पैकेट में से एक है

INSERT INTO ENTITYCLASSTEST (LASTNAME, NAME) VALUES ('sfirosijfhgdoi 0', 'dsufius0'), ('sfirosijfhgdoi 0', 'dsufius0'), ('sfirosijfhgdoi 0', 'dsufius0'), ('sfirosijfhgdoi 0', 'dsufius0')... and so on 

मैं इसे उम्मीद कर रहा था, जैसा कि ऊपर करने के लिए, लेकिन यह पैकेट प्रति एक लाइन डालने और नहीं कर रहा है प्रति पैकेट एकाधिक लाइनें। यहाँ

@Entity 
public class EntityClassTest implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    private String name; 
    private String lastname; 

    public EntityClassTest() { 
    } 

    public EntityClassTest(Long id, String name, String lastname) { 
     this.id = id; 
     this.name = name; 
     this.lastname = lastname; 
    } 

    public EntityClassTest(String name, String lastname) { 
     this.name = name; 
     this.lastname = lastname; 
    } 

    public Long getId() { 
     return id; 
    } 

    public String getName() { 
     return name; 
    } 

    public String getLastName() { 
     return lastname; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public void setLastName(String lastname) { 
     this.lastname = lastname; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 0; 
     hash += (id != null ? id.hashCode() : 0); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object object) { 
     // TODO: Warning - this method won't work in the case the id fields are not set 
     if (!(object instanceof EntityClassTest)) { 
      return false; 
     } 
     EntityClassTest other = (EntityClassTest) object; 
     if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return "database.EntityClassTest [id=" + id + " ]"; 
    } 

} 

और मेरी दृढ़ रहना विधि है कि एक List प्राप्त करता है और अंदर सभी वस्तुओं बनी रहती है:

यहाँ मेरी इकाई वर्ग है।

public void insertListToTable(final String persistenceUnit, final List list) throws SQLException { 
     final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnit); 
     final EntityManager entityManager = entityManagerFactory.createEntityManager(); 
     final EntityTransaction transaction = entityManager.getTransaction(); 

     try {    
      final int listSize = list.size(); 
      transaction.begin(); 

      for (int i = 0; i<listSize; i++) { //Object object : list) { 
       final Object object = list.get(i); 
       entityManager.persist(object); 

       if (i % 500 == 0) { //500, same as the JDBC batch size defined in the persistence.xml 
        //flush a batch of inserts and release memory: 
        entityManager.flush(); 
        entityManager.clear(); 
       } 
      } 
      transaction.commit(); 
     } 
     catch(Exception e) { 
      if (transaction != null) { 
       transaction.rollback(); 
      } 
      throw new SQLException(e.getMessage()); 
     } 
     finally { 
      entityManager.close(); 
     } 
    } 

और मेरे persistence.xml, जहां मैं 500 बैच मूल्य के रूप में स्थापित, फ़ाइल है:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> 
<persistence-unit name="ExternalServer" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> 
    <!-- List of Entity classes --> 
    <class>model.EntityClassTest</class> 
    <properties> 
     <property name="javax.persistence.jdbc.url" value="jdbc:mysql://myServer:3306/testdb?zeroDateTimeBehavior=convertToNull"/> 
     <property name="javax.persistence.jdbc.user" value="testdbuser"/> 
     <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> 
     <property name="javax.persistence.jdbc.password" value="myPassword"/> 
     <property name="javax.persistence.schema-generation.database.action" value="create"/> 

     <!-- Weaving --> 
     <property name="eclipselink.weaving" value="static"/> 
     <!-- SQL dialect/Database type --> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> 
     <property name="eclipselink.target-database" value="MySQL"/> 
     <!-- Tell the JPA provider to, by default, create the table if it does not exist. --> 
     <property name="javax.persistence.schema-generation.database.action" value="create"/> 
     <!-- No logging (For development change the value to "FINE") --> 
     <property name="eclipselink.logging.level" value="OFF"/> 
     <!-- Enable batch writing --> 
     <property name="eclipselink.jdbc.batch-writing" value="JDBC"/> 
     <!-- Batch size --> 
     <property name="eclipselink.jdbc.batch-writing.size" value="500"/> 

    </properties> 
    </persistence-unit> 
</persistence> 

तो मेरे सवाल है, यह क्यों नहीं बैच डालने है? मेरा मानना ​​है कि मैंने एक्लिप्ससेलिंक को ऐसा करने के लिए कॉन्फ़िगर किया है जो मैं ग्रहण लिंक वेबसाइट पर पढ़ रहा हूं और यहां भी SO।

//////////////////////////// EDIT //////////////// //////////

क्रिस के जवाब ने सुझाव दिया है, मैं @GeneratedValue(strategy = GenerationType.IDENTITY)@GeneratedValue(strategy = GenerationType.SEQUENCE) करने के लिए अपने EntityClassTest इस मूल्य में बदल गया है और परीक्षण फिर से चलाएं और पैकेट (छवि मैं की तरह से पहले के रूप में भेजे जा रहे हैं ऊपर पोस्ट)। तो यह मेरी समस्या को ठीक नहीं किया मैं डर रहा हूँ।

//////////////////////////// EDIT 2 /////////////// /////////

मैंने persistence.xml फ़ाइल में FINEST पर लॉगिंग स्तर बदल दिया है जैसा कि अगला दिखाया गया है।

<property name="eclipselink.logging.level" value="FINEST"/> 

और यहां लॉग उत्पन्न हुआ है। मैंने इसे पेस्टबिन में रखा क्योंकि यह काफी लंबा है।

http://pastebin.com/rKihCKMW

यह Execute query InsertObjectQuery काफी समय की एक बहुत बुला रहा है।

//////////////////////////// EDIT 3 /////////////// /////////

यहां उपयोग किए जा रहे प्रत्येक घटक के लिए संस्करण है।

+-------------------------+------------------------------+ 
| Variable_name   | Value      | 
+-------------------------+------------------------------+ 
| innodb_version   | 5.6.12      | 
| protocol_version  | 10       | 
| slave_type_conversions |        | 
| version     | 5.6.12-log     | 
| version_comment   | MySQL Community Server (GPL) | 
| version_compile_machine | x86_64      | 
| version_compile_os  | Win64      | 
+-------------------------+------------------------------+ 

Netbeans 8.0 

EclipseLink (JPA 2.1) 

mysql-connector-java-5.1.24.jar 

//////////////////////////// संपादित 4 //////////// ////////////

CuriousMind के जवाब के बाद मैं अपने EntityClassTest आईडी एनोटेशन संपादित किया है:

@Id 
    @GeneratedValue(strategy = GenerationType.AUTO, generator="id-seq-gen") 
    @SequenceGenerator(name="id-seq-gen", sequenceName="ID_SEQ_GEN", allocationSize=500) 
    private Long id; 

लेकिन यह मेरी समस्या का समाधान नहीं, मैं अभी भी कर रहा हूँ प्रति पैक एक एकल डालने (ऊपर की छवि द्वारा वर्णित) और EclipseLink लॉग पर मुझे मिल रहा है:

[EL Fine]: sql: 2014-10-19 06:44:02.608--ClientSession(824177287)--Connection(1674390738)--Thread(Thread[main,5,main])--SELECT LAST_INSERT_ID() 
[EL Finest]: sequencing: 2014-10-19 06:44:02.608--UnitOfWork(1985011414)--Thread(Thread[main,5,main])--assign sequence to the object (1.251 -> database.EntityClassTest [id=null ]) 
[EL Finest]: query: 2014-10-19 06:44:02.608--UnitOfWork(1985011414)--Thread(Thread[main,5,main])--Execute query InsertObjectQuery(database.EntityClassTest [id=null ]) 
[EL Finest]: query: 2014-10-19 06:44:02.608--ClientSession(824177287)--Thread(Thread[main,5,main])--Execute query ValueReadQuery(name="ID_SEQ_GEN" sql="SELECT LAST_INSERT_ID()") 
[EL Fine]: sql: 2014-10-19 06:44:02.608--ClientSession(824177287)--Connection(1674390738)--Thread(Thread[main,5,main])--INSERT INTO ENTITYCLASSTEST (LASTNAME, NAME) VALUES (?, ?) 
    bind => [sfirosijfhgdoi 2068, dsufius1034] 
[EL Fine]: sql: 2014-10-19 06:44:02.608--ClientSession(824177287)--Connection(1674390738)--Thread(Thread[main,5,main])--SELECT LAST_INSERT_ID() 
[EL Finest]: sequencing: 2014-10-19 06:44:02.608--UnitOfWork(1985011414)--Thread(Thread[main,5,main])--assign sequence to the object (1.252 -> database.EntityClassTest [id=null ]) 
[EL Finest]: query: 2014-10-19 06:44:02.608--UnitOfWork(1985011414)--Thread(Thread[main,5,main])--Execute query InsertObjectQuery(database.EntityClassTest [id=null ]) 
[EL Finest]: query: 2014-10-19 06:44:02.608--ClientSession(824177287)--Thread(Thread[main,5,main])--Execute query ValueReadQuery(name="ID_SEQ_GEN" sql="SELECT LAST_INSERT_ID()") 
[EL Fine]: sql: 2014-10-19 06:44:02.608--ClientSession(824177287)--Connection(1674390738)--Thread(Thread[main,5,main])--INSERT INTO ENTITYCLASSTEST (LASTNAME, NAME) VALUES (?, ?) 
    bind => [sfirosijfhgdoi 2244, dsufius1122] 

और इसी तरह ...

+0

क्या आप कृपया अपने द्वारा उपयोग किए जा रहे प्रत्येक सॉफ़्टवेयर के संस्करण पोस्ट कर सकते हैं, MySQL, ग्रहण लिंक, MySQL ड्राइवर इत्यादि – CuriousMind

+1

क्या आपने कनेक्शन गुणों में rewriteBatchedStatements = true जोड़ने का प्रयास किया था? –

+0

@ मार्सियोसोजा जुआनियर आप सही हैं। मैं 'persistence.xml' फ़ाइल में कनेक्शन के लिए' rewriteBatchedStatements = true' जोड़ना भूल गया था, मेरे पास यह मेरे जेडीबीसी में है और गलती से मैंने सोचा कि मेरे पास 'persistence.xml' में भी था। उस आंशिक रूप से मेरी समस्या हल हो गई। क्रिस के जवाब के साथ यह मेरी समस्या का समाधान किया। – dazito

उत्तर

3

आप अनुक्रमण के लिए GenerationType.IDENTITY उपयोग कर रहे हैं, जो एक-एक करके प्रत्येक डालने बयान एक की ID से पुन: प्राप्त करने की आवश्यकता है। एक अनुक्रमण योजना है कि 500 ​​के बैच में preallocation की अनुमति देता है की कोशिश करो और आप सुधार देखेंगे: http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Identity_sequencing

+0

मैंने अपने 'EntityClassTest' में यह मान' @GeneratedValue (strategy = GenerationType.IDENTITY) '' @GeneratedValue (strategy = GenerationType.SEQUENCE) 'में बदल दिया है और परीक्षण को फिर से चलाया है और पैकेट को पहले के रूप में भेजा जा रहा है (जैसे छवि मैंने अपने प्रश्न में पोस्ट किया)। तो यह मेरी समस्या को ठीक नहीं किया मैं डर रहा हूँ। – dazito

+0

आपको अपने बैच लेखन आकार से मेल खाने वाले बैच में अनुक्रम प्राप्त करने में सक्षम होना चाहिए, अन्यथा जेपीए को अतिरिक्त अनुक्रम मान प्राप्त करने के लिए बैच को इंटरप्ट करना होगा। मुझे विश्वास नहीं है कि MySQL अनुक्रमित है, इसलिए यह पहचान के लिए डिफ़ॉल्ट है; आपको इसके बजाय टेबल अनुक्रमण का उपयोग करने की आवश्यकता है। http://java-persistence-performance.blogspot.com/2011/06/how-to-improve-jpa-performance-by-1825.html?showComment=1379577956140#c4472664570410361957 देखें – Chris

0

ऐसा लगता है अनुक्रम पीढ़ी समस्या पैदा कर दिया गया है, तो आप इस post को देखें। यह preallocated अनुक्रम पीढ़ी के दृष्टिकोण प्रदान करता है।

0

यह एक साल पहले से ही हो चुका है, शायद उत्तर देने में बहुत देर हो चुकी है। मेरे मामले में, मैंने पाया कि फ्लश() समस्या का कारण बनता है। मैं प्रत्येक रिकॉर्ड के लिए लगातार() के बाद फ्लश() को कॉल करता हूं। यह खराब प्रदर्शन सम्मिलन में अनुकूलन और परिणाम बनाने के लिए बैच लेखन को रोकता है। फ्लश() को हटाने के बाद, सब ठीक हो गया।

0

यह क्रम/indentity की वजह से किया जा सकता है (preallocation उपयोग करने की आवश्यकता), लेकिन यह भी mysql के लिए मैं तुम्हें एक कनेक्शन स्ट्रिंग संपत्ति की जरूरत थोक डालने की अनुमति देने के बारे में सोच:

rewriteBatchedStatements = सच

jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true 
संबंधित मुद्दे