Hibernate Slow для получения соединения Postgres
Мне очень трудно отлаживать эту проблему. Всякий раз, когда я пытаюсь установить связь с 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
Я провел немного больше исследований по этому вопросу, пройдя через отладчик. У меня нет всего источника в моем classpath, но я все еще могу видеть переменные. В течение этой минуты ожидания Hibernate запрашивает таблицу pg_catalog.pg_type:
[SELECT typname FROM pg_catalog.pg_type WHERE oid = , ]
Вот скриншот:
7 ответов
Я исправил это =) Я действительно должен был болеть вокруг, чтобы найти ответ для этого. По сути, это сводится к загрузке метаданных и драйвера 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 );
Я должен был также включить hibernate.jdbc.use_get_generated_keys, в противном случае стратегия создания идентичности вызвала исключение. До этого он был включен автоматически на основе метаданных, полученных из БД. Таким образом, все мое решение состояло в том, чтобы добавить следующие две строки в файл persistence.xml:
<property name="hibernate.jdbc.use_get_generated_keys" value="true" />
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false" />
Спустя почти 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 против БД.
Не знаю, как ускорить это прямо сейчас, к счастью, это нужно один раз, а затем оно кешируется.
У меня были проблемы с прокручиваемым набором результатов, поэтому мне пришлось добавить третий параметр, см. Ниже:
<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>
Один сервер postgresql может содержать несколько баз данных. К сожалению, вы не можете скрыть метаданные других баз данных в одном соединении, поэтому чтение метаданных занимает много времени у jdbc-драйвера!
Разделяйте эти базы данных на разных postgres-серверах, и производительность чтения метаданных будет увеличена!
Читайте, как разделить на Centos.
Это звучит смутно, как проблема, которую мы видели в Ruby on Rails. Вы можете искать причину, похожую на ту, что я описал здесь:
http://archives.postgresql.org/pgsql-performance/2009-11/msg00128.php
Короче говоря, эта проблема была вызвана явной регистрацией драйвера JDBC из нескольких контекстов ClassLoader.
отключение
hibernate.temp.use_jdbc_metadata_defaults
может увеличить время запуска приложения, но отключить некоторые функции. Нравиться
batch
операции. Когда спящий режим не загружает метаданные jdbc, спящий режим устанавливает глобальный размер пакета равным 0, что означает отключение пакетных операций. В этом случае единственный способ использовать пакетную операцию с
session
сфера. Как показано ниже, пример кода
entityManager
.unwrap( Session.class )
.setJdbcBatchSize( 10 );
Так что будьте осторожны при отключении этого свойства