首页 > 解决方案 > Hibernate - 第一个 Sql 插入需要很长时间

问题描述

我正在尝试使用 Hibernate 在数据库中插入一条记录。数据被保存到数据库中的多个表中。在休眠方面,我有一个父实体类,它具有与其他实体类的一对一和一对多映射。在调试模式下,我可以看到保存操作导致多个 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 倍?

标签: sqlhibernate

解决方案


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


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


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


推荐阅读