web-dev-qa-db-fra.com

Hibernate lent pour acquérir Postgres Connection

J'ai vraiment du mal à déboguer ce problème. Chaque fois que j'essaie d'établir une connexion avec postgres, cela prend une minute entière. Une fois la connexion établie, tout va bien. J'ai essayé de désactiver tous les mappages et de ne pas en charger, mais la connexion met longtemps à se développer. J'ai aussi essayé de désactiver la validation, pas de différence. Lorsque j'utilise une simple connexion JDBC, c'est instantané. Hibernate fait quelque chose qui prend énormément de temps et je n'arrive pas à le réduire. Toute entrée est grandement appréciée!

Pilote Postgres:

postgresql-9.1-901.jdbc4.jar

Paramètres de configuration:

<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>

Paramètres supplémentaires dans le code:

    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");

Voici le segment de code où le délai se produit:

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;
    }

Voici les résultats du journal:

[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

J'ai fait un peu plus de recherches à ce sujet, en passant par le débogueur. Je n'ai pas toute la source dans mon classpath, mais je peux toujours voir les variables. Pendant cette minute d'attente, Hibernate interroge la table pg_catalog.pg_type:

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

Voici une capture d'écran:

DebugWindow

53
Jason Huntley

Je l'ai corrigé =) J'ai vraiment dû fouiller pour trouver la réponse à cette question. En gros, il s’agit de charger les métadonnées et le pilote JDBC. Il charge TOUTES LES DONNEES, y compris les commentaires à côté des colonnes SQL et d’autres constructions diverses, qui ne sont pas nécessaires au fonctionnement. Je ne sais pas pourquoi cette option est activée par défaut, mais vous devez absolument désactiver cette fonctionnalité, sauf si vous en avez explicitement besoin:

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

Connexion instantanée maintenant!

La seule information que je pourrais trouver sur ceci est dans le code:

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

112
Jason Huntley

Je devais également activer hibernate.jdbc.use_get_generated_keys, sinon la stratégie de génération d’identité lançait une exception. Auparavant, il était activé automatiquement en fonction des métadonnées reçues de la base de données. Donc toute ma solution a été d’ajouter les deux lignes suivantes à persistence.xml:

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

J'ai eu des problèmes avec les résultats défilables, j'ai donc dû ajouter le troisième paramètre, voir ci-dessous:

<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
Sebastien Plisson

Presque 7 ans plus tard et c'est toujours un problème ...

Désactiver la touche "temp" aide, mais il est gênant d'activer des propriétés une par une qui seraient configurées automatiquement (voir les autres réponses).

Dans le cas d’Oracle et de Teradata, je n’avais pas remarqué un tel ralentissement, j’ai alors creusé à fond et trouvé la partie la plus lente: https://github.com/pgjdbc/pgjdbc/blob/master/pgjdbc/src /main/Java/org/postgresql/jdbc/PgDatabaseMetaData.Java#L2237

Ce resultSet a dans mon cas 372 lignes (types). Ensuite, pour chaque pilote déclenche quelques appels depuis https://github.com/pgjdbc/pgjdbc/blob/master/pgjdbc/src/main/Java/org/postgresql/jdbc/TypeInfoCache.Java#L204 qui génère des tonnes d'instructions SQL par rapport à la base de données.

Aucune idée de la façon dont cela peut être accéléré pour le moment, heureusement, il faut une fois, puis elle est mise en cache.

1
zeratul021

Un serveur postgresql peut contenir plusieurs bases de données. Malheureusement, vous ne pouvez pas cacher les métadonnées des autres bases de données à une connexion , c’est pourquoi la lecture des métadonnées prend du temps par le pilote jdbc!

Séparez ces bases de données dans différents serveurs postgres et les performances de lecture de métadonnées seront améliorées!

Lire comment séparer les centos .

1
Peter Rader

Cela ressemble vaguement à un problème de Ruby on Rails. Vous pourriez rechercher une cause similaire à celle décrite ci-dessous:

http://archives.postgresql.org/pgsql-performance/2009-11/msg00128.php

En bref, ce problème était dû à l'enregistrement explicite du pilote JDBC à partir de plusieurs contextes ClassLoader.

0
kgrittn