Hibernate获取Postgres连接速度慢

67

我在调试这个问题时遇到了困难。每当我尝试与Postgres建立连接时,需要整整一分钟的时间。连接建立后,一切正常。我已经尝试禁用所有映射并不加载任何映射,但仍然需要很长时间才能获取连接。我还尝试过禁用验证,但没有任何区别。当我使用简单的JDBC连接时,它是瞬间完成的。Hibernate正在执行需要相当长时间的操作,但我似乎无法缩小范围。非常感谢您提供任何建议!

Postgres驱动程序:

postgresql-9.1-901.jdbc4.jar

配置设置:

<hibernate-configuration>
    <session-factory>
    <!-- properties -->
        <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
        <property name="connection.driver_class">org.postgresql.Driver</property>

        <property name="connection.url">jdbc:postgresql://xxxx.com:5432/xxxxx</property>
        <property name="connection.username">xxxxxxx</property>
        <property name="connection.password">xxxxxxx</property>

    </session-factory>
</hibernate-configuration>

代码中的其他设置:

    config.setProperty("hibernate.hbm2ddl.auto", hbm2ddlMode);
    //config.setProperty("hibernate.cache.use_query_cache", "true");
    config.setProperty("hibernate.cache.use_second_level_cache", "true");
    //config.setProperty("hibernate.cache.region.factory_class", "net.sf.ehcache.hibernate.EhCacheRegionFactory");
    config.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.EhCacheProvider");
    //config.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider");
    config.setProperty("hibernate.jdbc.fetch_size", "100");
    config.setProperty("hibernate.jdbc.batch_size", "30");
    config.setProperty("hibernate.jdbc.use_scrollable_resultset", "true");
    config.setProperty("hibernate.connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider");

    config.setProperty("hibernate.c3p0.acquire_increment", "1");
    config.setProperty("hibernate.c3p0.idle_test_period", "0");
    config.setProperty("hibernate.c3p0.min_size", "1");
    config.setProperty("hibernate.c3p0.max_size", "2");
    config.setProperty("hibernate.c3p0.timeout", "0");
    config.setProperty("javax.persistence.validation.mode", "none");

这是一个出现延迟的代码片段:

private SessionFactory buildSessionFactory() throws Exception {
        ServiceRegistry serviceRegistry  = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();

            //Building session takes a whole minute without mappings!!!
        sessionFactory = config.buildSessionFactory(serviceRegistry);

        validateConnection();

        return sessionFactory;
    }

以下是日志结果:

[main] 2012-04-09 10:40:32,823 110391 INFO  C3P0ConnectionProvider - HHH000046: 
Connection properties: {user=hgaidb_test, password=****}
[main] 2012-04-09 10:40:32,823 110391 INFO  C3P0ConnectionProvider - HHH000006: 
Autocommit mode: false
[main] 2012-04-09 10:40:34,100 111668 DEBUG JdbcServicesImpl - Database ->
       name : PostgreSQL
    version : 8.3.3
      major : 8
      minor : 3
[main] 2012-04-09 10:40:34,101 111669 DEBUG JdbcServicesImpl - Driver ->
       name : PostgreSQL Native Driver
    version : PostgreSQL 9.1 JDBC4 (build 901)
      major : 9
      minor : 1
*******************************************************************************
// 1 MINUTE DELAY
*******************************************************************************
[main] 2012-04-09 10:40:34,102 111670 DEBUG JdbcServicesImpl - JDBC version : 4.
0
[main] 2012-04-09 10:41:21,632 159200 INFO  Dialect - HHH000400: Using dialect: 
org.hibernate.dialect.PostgreSQLDialect
*******************************************************************************
[main] 2012-04-09 10:41:21,669 159237 INFO  LobCreatorBuilder - HHH000424: Disab
ling contextual LOB creation as createClob() method threw error : java.lang.refl
ect.InvocationTargetException
[main] 2012-04-09 10:41:21,814 159382 DEBUG SettingsFactory - Automatic flush du
ring beforeCompletion(): disabled
[main] 2012-04-09 10:41:21,814 159382 DEBUG SettingsFactory - Automatic session 
close at end of transaction: disabled
[main] 2012-04-09 10:41:21,815 159383 DEBUG SettingsFactory - JDBC batch size: 3
0
[main] 2012-04-09 10:41:21,816 159384 DEBUG SettingsFactory - JDBC batch updates
 for versioned data: disabled
[main] 2012-04-09 10:41:21,816 159384 DEBUG SettingsFactory - Scrollable result 
sets: enabled
[main] 2012-04-09 10:41:21,817 159385 DEBUG SettingsFactory - Wrap result sets: 
disabled
[main] 2012-04-09 10:41:21,818 159386 DEBUG SettingsFactory - JDBC3 getGenerated
Keys(): enabled
[main] 2012-04-09 10:41:21,818 159386 DEBUG SettingsFactory - JDBC result set fe
tch size: 100
[main] 2012-04-09 10:41:21,819 159387 DEBUG SettingsFactory - Connection release
 mode: auto
[main] 2012-04-09 10:41:21,819 159387 INFO  TransactionFactoryInitiator - HHH000
399: Using default transaction strategy (direct JDBC transactions)
[main] 2012-04-09 10:41:21,844 159412 DEBUG SettingsFactory - Default batch fetc
h size: 1
[main] 2012-04-09 10:41:21,844 159412 DEBUG SettingsFactory - Generate SQL with 
comments: disabled
[main] 2012-04-09 10:41:21,845 159413 DEBUG SettingsFactory - Order SQL updates 
by primary key: disabled
[main] 2012-04-09 10:41:21,846 159414 DEBUG SettingsFactory - Order SQL inserts 
for batching: disabled
[main] 2012-04-09 10:41:21,846 159414 DEBUG SettingsFactory - Query translator: 
org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory
[main] 2012-04-09 10:41:21,867 159435 INFO  ASTQueryTranslatorFactory - HHH00039
7: Using ASTQueryTranslatorFactory
[main] 2012-04-09 10:41:21,867 159435 DEBUG SettingsFactory - Query language sub
stitutions: {}
[main] 2012-04-09 10:41:21,867 159435 DEBUG SettingsFactory - JPA-QL strict comp
liance: disabled
[main] 2012-04-09 10:41:21,868 159436 DEBUG SettingsFactory - Second-level cache
: enabled
[main] 2012-04-09 10:41:21,868 159436 DEBUG SettingsFactory - Query cache: disab
led
[main] 2012-04-09 10:41:21,869 159437 DEBUG SettingsFactory - Cache region facto
ry : org.hibernate.cache.internal.NoCachingRegionFactory
[main] 2012-04-09 10:41:21,872 159440 DEBUG SettingsFactory - org.hibernate.cach
e.internal.NoCachingRegionFactory did not provide constructor accepting java.uti
l.Properties; attempting no-arg constructor.
[main] 2012-04-09 10:41:21,873 159441 DEBUG SettingsFactory - Optimize cache for
 minimal puts: disabled
[main] 2012-04-09 10:41:21,873 159441 DEBUG SettingsFactory - Structured second-
level cache entries: disabled
[main] 2012-04-09 10:41:21,873 159441 DEBUG SettingsFactory - Statistics: disabl
ed
[main] 2012-04-09 10:41:21,874 159442 DEBUG SettingsFactory - Deleted entity syn
thetic identifier rollback: disabled
[main] 2012-04-09 10:41:21,874 159442 DEBUG SettingsFactory - Default entity-mod
e: pojo
[main] 2012-04-09 10:41:21,875 159443 DEBUG SettingsFactory - Named query checki
ng : enabled
[main] 2012-04-09 10:41:21,875 159443 DEBUG SettingsFactory - Check Nullability 
in Core (should be disabled when Bean Validation is on): enabled
[main] 2012-04-09 10:41:21,876 159444 DEBUG SettingsFactory - multi-tenancy stra
tegy : NONE

我对这个问题进行了进一步的研究,通过调试器进行步骤推进。尽管我没有将所有源代码添加到类路径中,但我仍然能够查看变量。在那一分钟的等待期间,Hibernate正在查询pg_catalog.pg_type表:

[SELECT typname FROM pg_catalog.pg_type WHERE oid = , ]

以下是截图:

DebugWindow


这样的延迟可能是由DNS问题引起的,请尝试在connection.url中使用IP地址而不是域名来排除它。 - axtavt
我尝试使用IP,但获取时间没有任何变化。 - Jason Huntley
参见:https://dev59.com/XYDba4cB1Zd3GeqPBTUC - Dojo
一个问题已经在2014年发布到了Hibernate项目中:请参见https://hibernate.atlassian.net/browse/HHH-9124。截至本文撰写时,该问题仍然未解决。 - Stephan
7个回答

135

我修复了它 =) 在找到答案之前,我确实不得不深入研究。基本上,它归结于加载元数据和JDBC驱动程序。 它正在加载所有元数据,包括sql列旁边的注释和其他各种构造,这些都不需要进行操作。 我不知道为什么默认情况下会出现这种情况,但除非您明确需要它,否则应该关闭此功能:

config.setProperty("hibernate.temp.use_jdbc_metadata_defaults","false");

即时连接!

我能找到的唯一信息是代码中:

107     // 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value.
108     // The need for it is intended to be alleviated with future development, thus it is
109     // not defined as an Environment constant...
110     //
111     // it is used to control whether we should consult the JDBC metadata to determine
112     // certain Settings default values; it is useful to *not* do this when the database
113     // may not be available (mainly in tools usage).
114     boolean useJdbcMetadata = ConfigurationHelper.getBoolean( "hibernate.temp.use_jdbc_metadata_defaults", configValues, true );

http://grepcode.com/file/repo1.maven.org/maven2/org.hibernate/hibernate-core/4.1.1.Final/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java#JdbcServicesImpl


5
根据我的经验,为确保其有效运行,必须明确定义Hibernate方言。否则会导致应用程序在启动时出现故障(至少对于PostgreSQL 9.3和Hibernate 4而言)。 - chalda
1
禁用SchemaUpdate可能会受到影响。 - Njax3SmmM2x2a0Zf7Hpd
@momo是正确的。设置了这个属性似乎什么也没有改变。 - Opal
@Opal,我终于解决了这个问题,并在我的代码中使用了properties.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false");。我不确定是否还有其他事情我也做了,但你可以避免设置properties.put("hibernate.hbm2ddl.auto", "...");,而我没有这样做。也许这会有所帮助。 - mjs
11
这个在Spring Boot中对我不起作用。我将它添加为application.properties的一个属性,然后再次启动,它就开始起作用了:spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false - Dan Watt
显示剩余6条评论

11

我还必须启用 hibernate.jdbc.use_get_generated_keys 才能使 Identity 生成策略不会抛出异常。在此之前,它是基于从数据库接收到的元数据自动启用的。因此,我的整个解决方案是将以下两行添加到 persistence.xml 中:

<property name="hibernate.jdbc.use_get_generated_keys" value="true" />
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false" />

1
谢谢!使用了Hibernate 5.2,Spring Framework 4.3和PostgreSQL JDBC 4.2。 - Chu
请参考@CraigRinger的传奇,了解有关序列引起麻烦的更多细节,请查看此问题 - markdsievers

5

将近7年过去了,这仍然是一个问题...

关闭“temp”键可以帮助解决问题,但逐个启用应该自动配置的属性很麻烦(请参见其他答案)。

在Oracle和Teradata的情况下,我没有注意到这样的减速,所以我深入挖掘了一下,找到了最慢的部分: https://github.com/pgjdbc/pgjdbc/blob/master/pgjdbc/src/main/java/org/postgresql/jdbc/PgDatabaseMetaData.java#L2237

在我的情况下,此resultSet有372行(类型)。然后,对于每个驱动程序,从 https://github.com/pgjdbc/pgjdbc/blob/master/pgjdbc/src/main/java/org/postgresql/jdbc/TypeInfoCache.java#L204 发出几个调用,这会导致大量针对数据库的SQL语句。

目前不知道如何加快这个过程,幸运的是,它只需要一次,然后就会被缓存。


2
尽管这只需要一次,但在开发过程中这很烦人,因为我们需要等待很长时间才能看到我们所做的是否成功。 - Syakur Rahman
对于本地环境,如果设置Hibernate配置属性无效,您可以在hibernate-core-x.x.x.Final.jar:org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure():87处设置一个调试断点,并从Intellij的上下文菜单的'Evaluate Expression'选项中手动将useJdbcMetadata的值设置为false。 - undefined

3
我遇到了可滚动的结果集问题,因此我需要添加第三个参数,请看下面:
<property name="hibernate.temp.use_jdbc_metadata_defaults">false</property>
<property name="hibernate.jdbc.use_get_generated_keys">true</property>
<property name="hibernate.jdbc.use_scrollable_resultset">true</property>

1

0

0

禁用 hibernate.temp.use_jdbc_metadata_defaults 可能会增加应用程序的启动速度,但会禁用一些功能。例如 batch 操作。当 Hibernate 不加载 JDBC 元数据时,Hibernate 将全局批处理大小设置为 0,这意味着禁用了批处理操作。在这种情况下,使用 session 范围的批处理操作的唯一方法是像下面的代码示例一样。

entityManager
    .unwrap( Session.class )
    .setJdbcBatchSize( 10 );

因此,在禁用此属性时要小心


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接