java-对数据库进行9次查询后,执行相同查询的时间乘以7
作者:互联网
我在Windows 7 32上使用PostgreSQL(9.4.8).我正在通过Eclipselink 2.6.3和JDK 8u72上的JDBC驱动程序9.4.1208访问数据库.
我正在执行一个简单的计数查询(使用Criteria API构建).第一个查询花费一些时间,这没问题,此后,接下来的8个查询花费的时间略少,这很棒.然后,对于第9个查询,响应所花费的时间是前一个查询的7倍,并且永远不会下降.
这是我的日志的一部分:
[EL Fine]: sql: 2016-07-04 17:19:42.658--ServerSession(13112008)--Connection(27980113)--SELECT now()
INFO - SELECT now() = 2016-07-04 17:19:41.8
[EL Fine]: sql: 2016-07-04 17:19:42.691--ServerSession(13112008)--Connection(27980113)--SELECT version()
INFO - SELECT version() = PostgreSQL 9.4.8, compiled by Visual C++ build 1800, 32-bit
INFO - JDBC Version = PostgreSQL 9.4.1208
[EL Fine]: sql: 2016-07-04 17:19:42.738--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:19:42.726, 2016-07-04 17:19:42.726]
1 - count : 788166 - 3974
[EL Fine]: sql: 2016-07-04 17:19:46.244--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:19:46.241, 2016-07-04 17:19:46.241]
2 - count : 788166 - 1500
[EL Fine]: sql: 2016-07-04 17:19:49.745--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:19:49.742, 2016-07-04 17:19:49.742]
3 - count : 788166 - 1495
[EL Fine]: sql: 2016-07-04 17:19:53.242--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:19:53.239, 2016-07-04 17:19:53.239]
4 - count : 788166 - 1481
[EL Fine]: sql: 2016-07-04 17:19:56.723--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:19:56.72, 2016-07-04 17:19:56.72]
5 - count : 788166 - 1497
[EL Fine]: sql: 2016-07-04 17:20:00.219--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:20:00.217, 2016-07-04 17:20:00.217]
6 - count : 788166 - 1484
[EL Fine]: sql: 2016-07-04 17:20:03.705--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:20:03.703, 2016-07-04 17:20:03.703]
7 - count : 788166 - 1498
[EL Fine]: sql: 2016-07-04 17:20:07.203--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:20:07.201, 2016-07-04 17:20:07.201]
8 - count : 788166 - 1498
[EL Fine]: sql: 2016-07-04 17:20:10.701--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:20:10.7, 2016-07-04 17:20:10.7]
9 - count : 788166 - 1491
[EL Fine]: sql: 2016-07-04 17:20:14.193--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:20:14.192, 2016-07-04 17:20:14.192]
10 - count : 788166 - 7550
[EL Fine]: sql: 2016-07-04 17:20:23.742--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:20:23.741, 2016-07-04 17:20:23.741]
11 - count : 788166 - 7553
[EL Fine]: sql: 2016-07-04 17:20:33.296--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:20:33.295, 2016-07-04 17:20:33.295]
12 - count : 788166 - 7567
[EL Fine]: sql: 2016-07-04 17:20:42.864--ServerSession(13112008)--Connection(27980113)--SELECT COUNT(DISTINCT(ID)) FROM recorder.records WHERE ((channel_number IN (?, ......, ?, ?)) AND (rec_start BETWEEN ? AND ?))
bind => [10, 11, 12, ......, 299, 2016-03-04 17:20:42.863, 2016-07-04 17:20:42.863]
13 - count : 788166 - 7545
如您所见,第一个查询耗时3974毫秒,下一个查询约为1500毫秒,然后仅需> 7500毫秒!
可能出什么问题了?发生问题时,数据库不需要占用更多的CPU资源,我的程序也不需要.
解决方法:
看起来PostgreSQL使用的通用计划的性能比以前使用的计划差.
如果使用java.sql.PreparedStatement,则JDBC驱动程序将用参数代替前4次执行,并从第5次执行开始创建服务器端预处理语句,此语句将在以后使用(假设您使用默认值).连接参数prepareThreshold为5).
在接下来的5次执行中,PostgreSQL服务器将为该语句创建单独的计划,以替代传递的实际参数.
然后,它将创建一个通用计划(使用占位符代替查询参数),并且如果查询优化器估计此通用计划的性能不会比之前使用的特定计划差,则此通用计划将在以后使用.
因此,在这种情况下,前9个执行将使用与后续执行不同的计划,如果查询优化器选择错误,此后性能会下降.
我为您提供了两种选择:
>在PostgreSQL命令行上使用PREPARE为查询创建一个准备好的语句,然后使用EXPLAIN(ANALYZE)EXECUTE,将前5次执行的执行计划与之后使用的通用查询的执行计划进行比较(您可以看出来自占位符$1,$2等的通用查询).
希望您能找出为什么通用计划更糟的原因并改善您的查询.
>简单方法:阅读the documentation,如何通过将prepareThreshold设置为0来禁用此查询的服务器端prepare语句.
标签:postgresql,jpa-2-0,eclipselink,java 来源: https://codeday.me/bug/20191118/2028299.html