Tôi đang cố gắng tối ưu hóa việc triển khai JPA của tôi, bằng cách sử dụng EclipseLink. Tôi đã thêm hoạt động hàng loạt vào nó. Nhưng nó vẫn đang mất rất nhiều thời gian để làm 50 000 chèn. Phải mất hơn 10 lần thời gian cần thiết để thực hiện việc chèn chính xác bằng cách sử dụng SQL thô với JDBC.Chèn loạt EclipseLink rất rất chậm
Để đảm bảo hoạt động hàng loạt trong thực tế hoạt động, tôi đã sử dụng Wireshark để kiểm tra các gói của tôi và nó không sử dụng chèn hàng loạt.
Dưới đây là một trong những gói chèn:
Nó không được thực hiện:
INSERT INTO ENTITYCLASSTEST (LASTNAME, NAME) VALUES ('sfirosijfhgdoi 0', 'dsufius0'), ('sfirosijfhgdoi 0', 'dsufius0'), ('sfirosijfhgdoi 0', 'dsufius0'), ('sfirosijfhgdoi 0', 'dsufius0')... and so on
tôi đã mong đợi nó để làm như trên nhưng nó được chèn một dòng cho mỗi gói và không nhiều dòng cho mỗi gói.
Dưới đây là là Entity Lớp tôi:
@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 + " ]";
}
}
Và đây là kiên trì của tôi phương pháp mà nhận được một List
và vẫn tồn tại tất cả các đối tượng bên trong.
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();
}
}
Và persistence.xml
của tôi, nơi tôi đặt 500 là giá trị hàng loạt, tập tin là:
<?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>
Vì vậy, câu hỏi của tôi là, tại sao nó không batch chèn? Tôi tin rằng tôi đã cấu hình EclipseLink để làm như vậy từ những gì tôi đã đọc xung quanh trên trang web EclipseLink và ở đây SO là tốt.
/////////////////////////// EDIT //////////////// //////////
theo đề nghị của câu trả lời của Chris, tôi đã thay đổi trong EntityClassTest
của tôi giá trị này @GeneratedValue(strategy = GenerationType.IDENTITY)
-@GeneratedValue(strategy = GenerationType.SEQUENCE)
và tái chạy thử nghiệm và các gói được gửi như trước đây (như hình ảnh tôi đã đăng ở trên). Vì vậy, nó đã không sửa chữa vấn đề của tôi, tôi sợ.
//////////////////////////// EDIT 2 /////////////// /////////
Tôi đã thay đổi mức ghi nhật ký trong tệp persistence.xml
thành FINEST
như được hiển thị tiếp theo.
<property name="eclipselink.logging.level" value="FINEST"/>
Và đây là nhật ký được tạo. Tôi đặt nó vào một con nhộng vì nó khá dài.
Nó dường như được gọi Execute query InsertObjectQuery
khá nhiều lần.
//////////////////////////// EDIT 3 /////////////// /////////
Đây là phiên bản cho mỗi thành phần tôi đang sử dụng.
+-------------------------+------------------------------+
| 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
//////////////////////// EDIT 4 //////////// ////////////
Sau câu trả lời CuriousMind của tôi đã chỉnh sửa EntityClassTest
id chú thích của tôi để:
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator="id-seq-gen")
@SequenceGenerator(name="id-seq-gen", sequenceName="ID_SEQ_GEN", allocationSize=500)
private Long id;
Nhưng nó đã không giải quyết vấn đề của tôi, tôi vẫn còn nhận một gói đơn cho mỗi gói (như được mô tả bằng hình ảnh ở trên) và trên nhật ký EclipseLink
Tôi nhận được:
[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]
Và vân vân ...
Bạn có thể vui lòng đăng các phiên bản của từng phần mềm bạn đang sử dụng như, MySQL, Eclipse Link, trình điều khiển MySQL, v.v. – CuriousMind
Bạn có cố gắng thêm rewriteBatchedStatements = true vào thuộc tính kết nối không? –
@ MárcioSouzaJúnior bạn nói đúng. Tôi quên thêm 'rewriteBatchedStatements = true' vào kết nối trong tệp' persistence.xml' tôi có nó trong JDBC của mình và nhầm lẫn là tôi nghĩ rằng tôi đã có nó trong 'persistence.xml'. Điều đó giải quyết được một phần vấn đề của tôi. Với câu trả lời của Chris, nó đã giải quyết được vấn đề của tôi. – dazito