Hibernate - 第一个 Sql 插入需要很长时间

Posted

技术标签:

【中文标题】Hibernate - 第一个 Sql 插入需要很长时间【英文标题】:Hibernate - First Sql insert takes a long time 【发布时间】:2018-05-24 01:05:56 【问题描述】:

我正在尝试使用 Hibernate 在 DB 中插入一条记录。 数据被保存到数据库中的多个表中。在休眠方面,我有一个父实体类,它与其他实体类进行一对一和一对多映射。 在调试模式下,我可以看到保存操作导致多个 sql 插入。 第一个插入 sql 需要很长时间,大约 300 毫秒。 请注意:这不包括会话初始化、获取 JDBC 连接等所花费的时间。 10:46:24.132 [main] DEBUG org.hibernate.SQL - 插入 MY_SCHEMA_NAME.PARENT_ENTITY(COLUMN1、COLUMN2、COLUMN3、COLUMN4、COLUMN5、COLUMN6、COLUMN7、COLUMN8、COLUMN9、COLUMN10、COLUMN11、COLUMN12、COLUMN13、COLUMN14)值(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

如果我从任何其他工具(Oracle SQL 开发人员)执行相同的 sql,大约需要 20 毫秒。

hibernate 执行的后续 sql 插入只需要大约 15-20 毫秒。

问题是,为什么Hibernate中的第一个sql插入比后面的sql插入要花这么多时间,将近10倍?

【问题讨论】:

【参考方案1】:

要回答这个问题你需要学习:

如何在数据库端处理查询 - 请参阅:Oracle Database tuning guide - SQL processing 如何在客户端缓存查询 - 请参阅:Oracle Database JDBC developer's guide - Statement and resultset caching

简而言之:当 SQL 查询第一次从客户端发送到数据库时,那么数据库在执行此语句之前会执行一些额外的步骤(请参阅第一个链接)。在这第一次之后,该语句的 sql 计划被放入共享池(一种缓存),数据库可以跳过一些最耗时的任务(硬解析 - 优化和行源生成)以供所有后续请求此具体查询 - 此过程在上述链接的图表中称为“软解析”。 如果共享池被清除(例如在数据库重新启动后),则必须为第一个传入查询再次重复这些步骤 - 这需要额外的时间。 当查询引用的某些表/视图发生更改时(例如在 ALTER TABLE 命令或 CREATE/DROP INDEX 命令之后),该语句将从缓存中清除,并且数据库在此之后再次执行硬解析,这需要再来一次。


在客户端第一次执行语句时,它被放置在缓存中(参见第二个链接) - 这必须花费一些额外的时间。在此之后,对于所有后续语句调用,将从缓存中检索语句 - 这提高了性能。 当数据库驱动程序关闭时(例如在应用程序重新启动时),缓存被清除,并且下一个语句调用必须再次花费额外的时间。 您可以显式禁用语句缓存(详细说明请参见第二个 lnk),您很可能会看到所有执行的语句都需要更多时间。

【讨论】:

以上是关于Hibernate - 第一个 Sql 插入需要很长时间的主要内容,如果未能解决你的问题,请参考以下文章

Informix 数据库中的 Hibernate 批量插入(获取 sql 日志跟踪)

hibernate nativesqlquery批量插入

使用本机 SQL 创建表适用于 Hibernate/HSQLDB,插入失败。为啥?

Hibernate + JPA + jTDS + SQL Server = Unicode 问题

如何在 Hibernate、MySQL 应用程序中使用 import.sql 文件将默认数据插入表中

HIbernate 显示sql语句