为什么 JPA 需要时间从 close stmt 过渡到下一个 Prepare stmt

问题描述

我有执行简单查询的 JPA 语句。

我检查了日志, 它在可接受的时间内执行但是为了执行下一条语句需要时间来准备下一条语句

这里是日志

2021-03-01T12:35:42.008614Z    84 Prepare   SELECT * from table where id=?
2021-03-01T12:35:42.008810Z    84 Execute   SELECT * from table where id=4
2021-03-01T12:35:42.012826Z    84 Close stmt    
2021-03-01T12:35:42.033090Z    84 Prepare   SELECT * from table where id=?
2021-03-01T12:35:42.033279Z    84 Execute   SELECT * from table where id=5
2021-03-01T12:35:42.033860Z    84 Close stmt    
2021-03-01T12:35:42.054576Z    84 Prepare   SELECT * from table where id=?
2021-03-01T12:35:42.054792Z    84 Execute   SELECT * from table where id=6
2021-03-01T12:35:42.055372Z    84 Close stmt    

时间差可能看起来不大,但是这个语句要执行大约 1200+ 次,所以最后的延迟太多了

有什么办法可以减少转换时间(close 语句和下一个 prepare 语句之间的时间)?

中间没有语句或代码行导致任何时间延迟,循环中是单个语句

:更新->

通过在 application.yml 文件中启用 CachePrepStmt 属性,我设法减少了转换时间

所以新的转换时间大约是 0.1 毫秒,但现在执行时间是 20 毫秒

怎么会这样,有什么想法吗?

这里是新的日志语句

    
2021-03-02T06:20:51.249367Z    59 Execute   SELECT * from table where id=5
2021-03-02T06:20:51.269273Z    59 Reset stmt    
2021-03-02T06:20:51.269385Z    59 Execute   SELECT * from table where id=6
2021-03-02T06:20:51.289372Z    59 Reset stmt    
2021-03-02T06:20:51.289512Z    59 Execute   SELECT * from table where id=7
2021-03-02T06:20:51.308678Z    59 Reset stmt    
2021-03-02T06:20:51.308812Z    59 Execute   SELECT * from table where id=8
2021-03-02T06:20:51.328953Z    59 Reset stmt    
2021-03-02T06:20:51.329123Z    59 Execute   SELECT * from table where id=9
2021-03-02T06:20:51.348447Z    59 Reset stmt    

解决方法

首先,看起来您只是使用了准备好的语句。这种情况下不需要JPA,只要涉及到JDBC PreparedStatement就足够了。

其次,您可以像这样使用“in”谓词来减少工作量:

SELECT * from table where id in (4,5,6,7,8,9)

如果“id”是主键或索引字段,则会产生足够快的单个选择。但是不要忘记检查查询的长度是否合理。

另一种选择是选择一个 id 范围

SELECT * from table where id between 4 and 9

然后根据需要在客户端过滤结果,只需跳过不必要的 ID。