需要在 5 秒内使用 hibernate 在 mysql 中插入 100000 行

2024-03-22

我正在尝试使用 Hibernate(JPA) 在 5 秒内向 MYSQL 表中插入 100,000 行。我已经尝试了 hibernate 提供的所有技巧,但仍然无法做得比 35 秒更好。

第一个优化:我从 IDENTITY 序列生成器开始,这导致插入需要 60 秒。后来我放弃了序列生成器并开始分配@Id通过阅读来充实自己MAX(id)并使用AtomicInteger.incrementAndGet()自己分配字段。这将插入时间缩短至 35 秒。

第二次优化:我通过添加启用了批量插入

<prop key="hibernate.jdbc.batch_size">30</prop> <prop key="hibernate.order_inserts">true</prop> <prop key="hibernate.current_session_context_class">thread</prop> <prop key="hibernate.jdbc.batch_versioned_data">true</prop>

到配置。我惊讶地发现批量插入完全没有减少插入时间。还有35秒!

现在,我正在考虑尝试使用多线程插入。 有人有任何指点吗?我应该选择 MongoDB 吗?

下面是我的配置: 1.休眠配置 `

<bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.progresssoft.manishkr" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
                <prop key="hibernate.jdbc.batch_size">30</prop>
                <prop key="hibernate.order_inserts">true</prop>
                <prop key="hibernate.current_session_context_class">thread</prop>
                <prop key="hibernate.jdbc.batch_versioned_data">true</prop>
            </props>
        </property>
    </bean>

    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
          id="dataSource">
        <property name="driverClassName" value="${database.driver}"></property>
        <property name="url" value="${database.url}"></property>
        <property name="username" value="${database.username}"></property>
        <property name="password" value="${database.password}"></property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactoryBean" />
    </bean>



    <tx:annotation-driven transaction-manager="transactionManager" />

`

  1. 实体配置:

`

@Entity
@Table(name = "myEntity")
public class MyEntity {

    @Id
    private Integer id;

    @Column(name = "deal_id")
    private String dealId;

    ....
    ....

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "timestamp")
    private Date timestamp;

    @Column(name = "amount")
    private BigDecimal amount;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "source_file")
    private MyFile sourceFile;

    public Deal(Integer id,String dealId, ....., Timestamp timestamp, BigDecimal amount, SourceFile sourceFile) {
        this.id = id;
        this.dealId = dealId;
        ...
        ...
        ...
        this.amount = amount;
        this.sourceFile = sourceFile;
    }


    public String getDealId() {
        return dealId;
    }

    public void setDealId(String dealId) {
        this.dealId = dealId;
    }

   ...

   ...


    ....

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }

    ....


    public Integer getId() {
        return id;
    }

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

`

  1. 持久代码(服务):

`

@Service
@Transactional
public class ServiceImpl implements MyService{

    @Autowired
    private MyDao dao;
....

`void foo(){
        for(MyObject d : listOfObjects_100000){
            dao.persist(d);
        }
}

` 4.Dao类:

`

@Repository
public class DaoImpl implements MyDao{

    @PersistenceContext
    private EntityManager em;

    public void persist(Deal deal){
        em.persist(deal);
    }
}

`

Logs: `

DEBUG o.h.e.j.b.internal.AbstractBatchImpl - Reusing batch statement
18:26:32.906 [http-nio-8080-exec-2] DEBUG org.hibernate.SQL - insert into deal (amount, deal_id, timestamp, from_currency, source_file, to_currency, id) values (?, ?, ?, ?, ?, ?, ?)
18:26:32.906 [http-nio-8080-exec-2] DEBUG o.h.e.j.b.internal.AbstractBatchImpl - Reusing batch statement
18:26:32.906 [http-nio-8080-exec-2] DEBUG org.hibernate.SQL - insert into deal (amount, deal_id, timestamp, from_currency, source_file, to_currency, id) values (?, ?, ?, ?, ?, ?, ?)
18:26:32.906 [http-nio-8080-exec-2] DEBUG o.h.e.j.b.internal.AbstractBatchImpl - Reusing batch statement
18:26:32.906 [http-nio-8080-exec-2] DEBUG org.hibernate.SQL - insert into deal (amount, deal_id, timestamp, from_currency, source_file, to_currency, id) values (?, ?, ?, ?, ?, ?, ?)
18:26:32.906 [http-nio-8080-exec-2] DEBUG o.h.e.j.b.internal.AbstractBatchImpl - Reusing batch statement
18:26:32.906 [http-nio-8080-exec-2] DEBUG org.hibernate.SQL - insert into deal (amount, deal_id, timestamp, from_currency, source_file, to_currency, id) values (?, ?, ?, ?, ?, ?, ?)
18:26:32.906 [http-nio-8080-exec-2] DEBUG o.h.e.j.b.internal.AbstractBatchImpl - Reusing batch statement
18:26:32.906 [http-nio-8080-exec-2] DEBUG org.hibernate.SQL - insert into deal (amount, deal_id, timestamp, from_currency, source_file, to_currency, id) values (?, ?, ?, ?, ?, ?, ?)
18:26:32.906 [http-nio-8080-exec-2] 

... ...

DEBUG o.h.e.j.b.internal.AbstractBatchImpl - Reusing batch statement
18:26:34.002 [http-nio-8080-exec-2] DEBUG org.hibernate.SQL - insert into deal (amount, deal_id, timestamp, from_currency, source_file, to_currency, id) values (?, ?, ?, ?, ?, ?, ?)
18:26:34.002 [http-nio-8080-exec-2] DEBUG o.h.e.j.b.internal.AbstractBatchImpl - Reusing batch statement
18:26:34.002 [http-nio-8080-exec-2] DEBUG org.hibernate.SQL - insert into deal (amount, deal_id, timestamp, from_currency, source_file, to_currency, id) values (?, ?, ?, ?, ?, ?, ?)
18:26:34.002 [http-nio-8080-exec-2] DEBUG o.h.e.j.b.internal.AbstractBatchImpl - Reusing batch statement
18:26:34.002 [http-nio-8080-exec-2] DEBUG org.hibernate.SQL - insert into deal (amount, deal_id, timestamp, from_currency, source_file, to_currency, id) values (?, ?, ?, ?, ?, ?, ?)
18:26:34.002 [http-nio-8080-exec-2] DEBUG o.h.e.j.b.internal.AbstractBatchImpl - Reusing batch statement
18:26:34.002 [http-nio-8080-exec-2] DEBUG org.hibernate.SQL - insert into deal (amount, deal_id, timestamp, from_currency, source_file, to_currency, id) values (?, ?, ?, ?, ?, ?, ?)
18:26:34.002 [http-nio-8080-exec-2] DEBUG o.h.e.j.batch.internal.BatchingBatch - Executing batch size: 27
18:26:34.011 [http-nio-8080-exec-2] DEBUG org.hibernate.SQL - update deal_source_file set invalid_rows=?, source_file=?, valid_rows=? where id=?
18:26:34.015 [http-nio-8080-exec-2] DEBUG o.h.e.j.batch.internal.BatchingBatch - Executing batch size: 1
18:26:34.018 [http-nio-8080-exec-2] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - committed JDBC Connection
18:26:34.018 [http-nio-8080-exec-2] DEBUG o.h.e.t.i.jdbc.JdbcTransaction - re-enabling autocommit
18:26:34.032 [http-nio-8080-exec-2] DEBUG o.s.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@2354fb09] after transaction
18:26:34.032 [http-nio-8080-exec-2] DEBUG o.s.o.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
18:26:34.032 [http-nio-8080-exec-2] DEBUG o.h.e.j.internal.JdbcCoordinatorImpl - HHH000420: Closing un-released batch
18:26:34.032 [http-nio-8080-exec-2] DEBUG o.h.e.j.i.LogicalConnectionImpl - Releasing JDBC connection
18:26:34.033 [http-nio-8080-exec-2] DEBUG o.h.e.j.i.LogicalConnectionImpl - Released JDBC connection

'


在尝试了所有可能的解决方案之后,我终于找到了一个在 5 秒内插入 100,000 行的解决方案!

我尝试过的事情:

1)使用 AtomicInteger 将 hibernate/database AUTO INCRMENT/GENERATED id 替换为自行生成的 ID

2) 启用batch_inserts且batch_size=50

3) 在每一次“batch_size”次 persist() 调用后刷新缓存

4)多线程(没有尝试这个)

最后有效的是使用原生多插入查询并在一个sql插入查询中插入1000行而不是使用坚持()在每个实体上。为了插入 100,000 个实体,我创建了一个像这样的本机查询"INSERT into MyTable VALUES (x,x,x),(x,x,x).......(x,x,x)"[一个sql插入查询中插入1000行]

现在插入10万条记录大约需要3秒!所以瓶颈是 Orm 本身!对于批量插入,唯一有效的似乎是本机插入查询!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

需要在 5 秒内使用 hibernate 在 mysql 中插入 100000 行 的相关文章

  • javax.persistence.TransactionRequiredException:没有可用于当前线程的实际事务的 EntityManager

    我使用 Hibernate 创建了我的第一个 Spring MVC 项目 我的 DAO 层使用 JPA EntityManager 与数据库交互 GenericDao java Repository public abstract clas
  • 为什么Java中的文件名与公共类名相同? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在Java中 文件名应该与文件名相同public class包含在该文件中 为什么这是一个限制 它有什么目的 Java 有一个有趣的方法 如果给
  • 限制 JPQL 中的结果数量

    如何限制从数据库检索结果的数量 select e from Entity e I need only 10 results for instance 您可以尝试像这样给出 10 个要显式获取的结果 entityManager createQ
  • Java - toString 到 Color

    我一整天都在努力解决这个问题 基本上我做了一个 for 循环 将条目添加到数组列表中 其中一项是 颜色 变量 我已经用过random nextInt为颜色构造函数的红色 绿色和蓝色部分创建新值 我还设置了一个toString方法 这样我就可
  • 外部实体更改后索引不更新

    我目前正在开发一个项目 使用 JPA 2 1 保存数据并使用 hibernate search 4 5 0 final 搜索实体 映射类和索引后 搜索工作正常 但是 当我更改值时描述B 类从 someStr 到 anotherStr 数据库
  • 如何使用 Swipe 视图实现 Android TabLayout 设计支持库

    我将使用 android TabLayout 设计支持库 但我不知道如何使用滑动视图 这是我的代码 XML
  • java 中的 Try-with-resources 和 return 语句

    我想知道是否放一个return里面的声明尝试资源block 防止资源自动关闭 try Connection conn return conn createStatement execute 如果我写这样的东西将会联系被关闭 Oracle 文
  • 在 Java 中的 JFrame/JPanel/JComponent 中添加 Web 浏览器

    我正在开发一个 Java 应用程序 需要在应用程序中使用 Web 浏览器 我见过一些应用程序这样做 例如在同一应用程序中单击左侧面板中的提要并打开右侧面板中的链接时的 RSS 阅读器 我想实现类似的功能 在java中可以做到这一点吗 Jav
  • 使用 equals 方法比较两个对象,Java

    我有一个对象数组 我想将它们与目标对象进行比较 我想返回与目标对象完全匹配的对象的数量 这是我的计数方法 public int countMatchingGhosts Ghost target int count 0 for int i 0
  • 连接 3 三张表

    我有这个图表应该可以解释我的情况 我需要一些关于连接 3 个表的帮助 我不知道如何做这种事情 因此 我可以通过执行以下操作来经历一段检索记录的 while 循环 img src alt Album AlbumID 使用内部联接 http w
  • Hazelcast:连接到远程集群

    我们有一组 Hazelcast 节点 全部运行在一个远程系统 具有许多节点的单个物理系统 上 我们希望从外部客户端连接到该集群 一个 Java 应用程序 它使用如下代码连接到 Hazelcast ClientConfig clientCon
  • 如何将测试类打包到jar中而不运行它们?

    我正在努力将我的测试类包含到 jar 包中 但不运行它们 经过一番谷歌搜索后 我尝试过mvn package DskipTests 但我的测试类根本没有添加到 jar 中 有任何想法吗 如果您遵循 Maven 约定 那么您的测试类位于src
  • 单元测试、集成测试还是设计中的问题?

    我编写了我的第一个单元测试 我认为它过于依赖其他模块 我不确定是否是因为 这是一个复杂的测试 我实际上已经编写了集成测试或 我的设计有问题 我首先要说的是 虽然我有大约 4 年的开发经验 但我从未学过 也没有人教过自动化测试 我刚刚使用 H
  • 如何从 Trie 中检索给定长度的随机单词

    我有一个简单的 Trie 用来存储大约 80k 长度为 2 15 的单词 它非常适合检查字符串是否是单词 但是 现在我需要一种获取给定长度的随机单词的方法 换句话说 我需要 getRandomWord 5 来返回 5 个字母的单词 所有 5
  • 线程上下文类加载器和普通类加载器的区别

    线程的上下文类加载器和普通类加载器有什么区别 也就是说 如果Thread currentThread getContextClassLoader and getClass getClassLoader 返回不同的类加载器对象 将使用哪一个
  • 动态创建 JSON 对象

    我正在尝试使用以下格式创建 JSON 对象 tableID 1 price 53 payment cash quantity 3 products ID 1 quantity 1 ID 3 quantity 2 我知道如何使用 JSONOb
  • 内部类的访问修饰符[重复]

    这个问题在这里已经有答案了 可能的重复 受保护 公共内部类 https stackoverflow com questions 595179 protected public inner classes 我确信这个问题已经被问过 但我找不到
  • 在java中创建一个XML树并将其转换为json对象

    我尝试创建也能够转换为 json 的树 但对于只有一个xpath 当我尝试实现多个 xpath 时 我无法获得所需的输出 这里我分享一下我的实现 private static Document addElemtbypath List
  • 设置 Firefox 配置文件以使用 Selenium 和 Java 自动下载文件

    我想使用 Selenium WebDriver 和 Java 验证文件下载 要下载的文件为 PDF 格式 当 WebDriver 单击 AUT 中的 下载 链接时 Firefox 将打开以下下载确认窗口 我希望 Firefox 自动下载文件
  • mod_rewrite, .htaccess 连接mysql数据库

    我希望 htaccess 文件中的 mod rewrite 链接到 mysql 数据库以向我提供映射信息 具体来说 我使用单个代码库来托管多个站点 因此 如果用户请求图像 例如 http www example com images car

随机推荐

  • C 数组中的指针递增

    我试图理解下面的程序 具体来说 定义cur name以及指针的递增cur age在 printf 语句中 cur age i 必须索引数组中的每个整数 但我希望它指向内存中的连续地址 而不是给定 int 的下一个整数是 4 个字节 即为什么
  • ASP.NET MVC:可用路由数据的 Uri

    我的问题很简单 我有一个 Uri 我想弄清楚它映射到哪个路由 这样我就可以对路由的各个部分进行一些检查 控制器 操作等 如何从 Uri 转到 RouteData 或 Route 根据 tvanfosson 的指导 我想出了一个可以满足我需要
  • 测试 Bash 函数返回值的正确方法是什么?

    我想测试 Bash 函数的返回值if像这样的声明 if func arg then 但我收到如下错误消息 conditional binary operator expected 这样做的正确方法是什么 是下面这个吗 if func arg
  • 字符串未被识别为有效的日期时间

    我收到此错误 字符串未被识别为有效的日期时间 代码如下 DateTimeOffSet dt new DateTimeOffset Convert ToDateTime DateTime Now ToString dd MM yyyy hh
  • 使用 Service Worker 和推送通知做出反应

    一些初步考虑 react 16 8 2 react scripts 2 1 5 我创建了一个新的反应应用程序 我需要实现推送通知 下列的this https developers google com web fundamentals co
  • Go 保证地址不变吗?

    给定一个对象obj有保证吗 uintptr unsafe Pointer obj 无论何时调用 都会计算出相同的值 当然 Go 保证如果你使用两个指向同一个对象的指针 它们总是比较相等 不过 实现可能会移动内存中的对象并透明地更新指向它的所
  • 什么是会话和会话变量?

    您能指导我什么是会话和会话变量吗 我不需要比较 ASP 会话和 ASP NET 会话 因为我对 ASP 一无所知 我也看过很多关于会话类型的文章 但我仍然无法正确理解 ASP NET 中什么是会话以及什么是会话变量 会话 是跟踪每个用户的请
  • PHP:Html 以 html 格式发送电子邮件

    我正在遵循教程http css tricks com sending nice html email with php http css tricks com sending nice html email with php 以 html
  • 获取 RFECV scikit-learn 中的功能

    受此启发 http scikit learn org stable auto examples feature selection plot rfe with cross validation html sphx glr auto exam
  • 如何在 Rails 3.1 中初始化 ActionDispatch::ParamsParser?

    我的应用程序为其 Rest 接口定义了一个自定义 Mime 类型 所以我将其注册在mime types rb初始化器 Mime Type register application vnd example app v1 xml xml v1
  • 当所有线程完成时

    这是我第一次真正尝试使用多线程 我想知道如何判断所有任务组何时完成运行 for int i 0 i lt taskGroups Count i ThreadStart t delegate RunThread taskGroups i ne
  • 自定义 jQuery-File-Upload(基本插件)

    我碰到jQuery 文件上传 https github com blueimp jQuery File Upload在谷歌搜索中 我发现它很简洁 正是我所需要的 但我遇到了一个小问题 即使用基本插件按照我希望的方式获取几个功能 我认为基本插
  • 如何将日期输入和时间输入视为当地时间,而不是世界时间?

    用户输入的日期输入2019 12 22给出这些值 input value 2019 12 22 input valueAsNumber 1576972800000 input valueAsDate Sat Dec 21 2019 16 0
  • 多个构建风格的 applicationId 清单占位符不起作用

    我正在修改当前的 android 项目 以便它可以安装在同一设备上以实现多种风格和构建配置 构建 gradle defaultConfig applicationId com myapp manifestPlaceholders manif
  • Windows 窗体中的十进制文本框

    我正在做一个 Financial Winforms 应用程序 但在控件方面遇到了一些问题 我的客户需要在各处插入小数值 价格 折扣等 我想避免一些重复验证 因此 如果不是因为焦点和蒙版的长度 我立即尝试了能够满足我的需求的 MaskedTe
  • SQL Server:大块数据库查询

    我正在使用 Microsoft SQL Server Management Studio 我对 SQL Server 的专业知识很少 但我过去使用过 MySQL 并且非常擅长 我的问题是 我有一个相当大的数据库 有超过 1 3 亿条记录 我
  • 将 phpseclib 集成到 Laravel 5

    我目前正在将我的项目从 Laravel 4 迁移到 Laravel 5 我仍然是 Laravel 和 OOP 的新手用户 但到目前为止一切都很顺利 但是 在我的 L4 项目中 我使用 phpseclib 生成 SSH 密钥 并通过以下方式导
  • Gmail 的 HTML 电子邮件签名显示方式不同

    我使用 Thunderbird 作为我的主要工作邮件客户端 我刚刚创建了一个新的 HTML 签名 它可以在 Thunderbird Opera 和在线 HTML 查看器中正确显示 但不能在 GMail 上显示 如果有人能指出问题所在的方向
  • 在 R 中的函数内保存单个对象:RData 文件大小非常大

    我试图在 R 中保存修剪后的 GLM 对象 即所有 非必要 特征设置为 NULL 例如残差 prior weights qr qr 举个例子 看看我需要执行此操作的最小对象 print object size glmObject 16899
  • 需要在 5 秒内使用 hibernate 在 mysql 中插入 100000 行

    我正在尝试使用 Hibernate JPA 在 5 秒内向 MYSQL 表中插入 100 000 行 我已经尝试了 hibernate 提供的所有技巧 但仍然无法做得比 35 秒更好 第一个优化 我从 IDENTITY 序列生成器开始 这导