1

I'm inserting 2500 records from Hibernate into a totally empty MySQL table. The insert is taking 5 minutes!

I've googled for hours and tried a few things like an autogenerated primary key but nothing seems to improve the performance.

An earlier version of my program was doing inserts concurrently (1 per thread with ~100 threads) and that was taking ~2 minutes. I thought batching should improve performance by ~10x but it seems to have backfired.

I'm using Google Cloud's MySQL with a db-f1-micro instance

This is what my table looks like (only table in the DB!):

CREATE TABLE `categories` ( `browse_node` varchar(60) NOT NULL, `name` varchar(60) DEFAULT NULL, `path` varchar(400) DEFAULT NULL, `url` varchar(200) NOT NULL, `level` int(11) NOT NULL, PRIMARY KEY (`browse_node`) ) 

This is the POJO:

package example.com; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; /** * Represents a category from the categories table */ @Entity @Table(name = "categories") public class Category { @Id @Column(name = "browse_node") private String browseNode; @Column(name = "name") private String name; @Column(name = "path") private String path; @Column(name = "url") private String url; @Column(name = "level") private int level; public Category() { } public Category(String browseNode, String name, String path, String url, int level) { this.browseNode = browseNode; this.name = name; this.path = path; this.url = url; this.level = level; } // Omitting setters/getters } 

Here's the code doing the insertion:

private static void writeCategoriesToDb(Map<String, Category> categories) { StatelessSession session = sessionFactory.openStatelessSession(); // Session session = sessionFactory.openSession(); session.beginTransaction(); int i = 0; int batchSize = 50; for (Category category : categories.values()) { session.insert(category); // if (i % batchSize == 0) { // session.flush(); // session.clear(); // } // i++; } session.getTransaction().commit(); session.close(); } 

And here's the config file:

<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://someIp/myDB</property> <property name="connection.username">root</property> <property name="connection.password">password</property> <property name="connection.useSSL">false</property> <!-- JDBC connection pool (use the built-in) --> <property name="connection.pool_size">20</property> <property name="hibernate.jdbc.batch_size">3000</property> <property name="hibernate.id.new_generator_mappings">false</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <mapping class="example.com.Category"/> </session-factory> </hibernate-configuration> 
0

1 Answer 1

9

Found the answer here.

Adding rewriteBatchedStatements=true to my JDBC url fixed it!

It now takes ~2.2 seconds to insert all the records.

<property name="connection.url">jdbc:mysql://someIp/myDB?rewriteBatchedStatements=true</property> 
Sign up to request clarification or add additional context in comments.

1 Comment

Wonderful - it is important to accept your answer by clicking the pipe, to show the googlers of the future, that this question is answered already.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.