я должен активировать пул операторов c3p0? - PullRequest
18 голосов
/ 27 мая 2010

мы запускаем стек java6 / hibernate / c3p0 / postgresql. Наш драйвер JDBC 8.4-701.jdbc3

У меня есть несколько вопросов о подготовленных заявлениях. я прочитал Отличный документ о Подготовленные заявления

Но у меня все еще есть вопрос, как настроить c3p0 с помощью postgresql.

На данный момент имеем

 c3p0.maxStatements = 0
 c3p0.maxStatementsPerConnection  =   0

В моем понимании подготовленные операторы и объединение операторов - это две разные вещи:

В нашем стеке hibernate используются подготовленные операторы. Postgresql кеширует план выполнения. В следующий раз, когда используется то же утверждение, postgresql повторно использует план выполнения. Это экономит время планирования внутри БД.

Кроме того, c3p0 может кэшировать Java-экземпляры "java.sql.PreparedStatement". Это означает, что он кэширует объект Java. Так что при использовании
c3p0.maxStatementsPerConnection = 100 кэширует не более 100 различных
объекты. Это экономит время на создание объектов, но это не имеет ничего общего с база данных postgresql и ее подготовленные заявления.

правый

Поскольку мы используем около 100 различных утверждений, я бы установил c3p0.maxStatementsPerConnection = 100

Но в документах c3p0 говорится о c3p0 известных недостатках

Издержки пула операторов слишком высоко. Для водителей, которые не выполнить значительную предварительную обработку PreparedStatements, пул накладные расходы перевешивают любые сбережения. Таким образом, пул операторов отключен по умолчанию. Если ваш водитель делает Preprocess PreparedStatements, особенно если это происходит через IPC с СУРБД, вы, вероятно, увидите значительный прирост производительности Включение пула операторов (Сделай это установив свойство конфигурации maxStatements или maxStatementsPerConnection к значению больше нуля.).

Итак: Разумно ли активировать maxStatementsPerConnection с помощью c3p0 и Postgresql? Есть ли реальная польза от его активации?

С уважением Janning

Ответы [ 2 ]

25 голосов
/ 27 мая 2010

Я не помню, чтобы Hibernate действительно сохранял экземпляры PreparedStatement сам или полагался на то, что провайдер соединений использует их повторно. (Быстрое сканирование BatcherImpl предполагает, что он повторно использует последний PreparedStatement при выполнении одного и того же SQL несколько раз подряд)

Я думаю, что документация c3p0 пытается подчеркнуть, что для многих драйверов JDBC PreparedStatement бесполезен: некоторые драйверы в конечном итоге просто объединяют параметры на стороне клиента и затем передают встроенный оператор SQL в база данных в любом случае. Для этих драйверов PreparedStatements не имеют никакого преимущества, и любые попытки их повторного использования напрасны. (В Postgresql JDBC FAQ сказано, что это имело место в Postgresql до версии 3 протокола протокола, и более подробную информацию можно найти в документации ).

Для драйверов, которые обрабатывают PreparedStatements с пользой, все же, вероятно, необходимо фактически использовать экземпляры PreparedStatement, чтобы получить какую-либо выгоду. Например, если драйвер реализует:

  • Connection.prepareStatement (sql) - создать оператор на стороне сервера
  • PreparedStatement.execute (..) и т. Д. - выполнить этот оператор на стороне сервера
  • PreparedStatement.close () - освободить серверную инструкцию

Учитывая это, если приложение всегда открывает подготовленный оператор, выполняет его один раз, а затем снова закрывает, все равно не принесет никакой пользы; на самом деле, это могло бы быть и хуже, так как в настоящее время потенциально больше поездок туда и обратно. Таким образом, приложение должно держаться за экземпляры PreparedStatement. Конечно, это приводит к другой проблеме: если приложение слишком сильно зависает, и каждый оператор на стороне сервера потребляет некоторые ресурсы, это может привести к проблемам на стороне сервера. В случае, когда кто-то использует JDBC напрямую, этим можно управлять вручную - некоторые операторы, как известно, могут быть использованы повторно и, следовательно, подготовлены; некоторые нет, и вместо этого просто используют временные экземпляры Statement. (Это пропускает другое преимущество готовых операторов: обработка аргумента, экранирующего)

Вот почему c3p0 и другие пулы соединений также имеют подготовленные кеши операторов - это позволяет коду приложения избегать всего этого. Операторы обычно хранятся в каком-то ограниченном пуле LRU, поэтому общие операторы повторно используют экземпляр PreparedStatement.

Последними частями головоломки являются то, что драйверы JDBC сами могут решить быть умными и сделать это; и сами серверы могут также решить быть хитрыми и обнаружить клиента, отправляющего заявление, которое структурно аналогично предыдущему.

Учитывая, что Hibernate сам не хранит кэш экземпляров PreparedStatement, вам нужно сделать так, чтобы c3p0 использовал их. (Которые должны быть уменьшены накладные расходы для общих операторов из-за повторного использования кэшированных планов). Если c3p0 не кэширует подготовленные операторы, то драйвер просто увидит, как приложение готовит оператор, выполняет его, а затем снова закрывает. Похоже, что драйвер JDBC имеет настройку «порогового значения» для избежания нагрузки на сервер подготовки / выполнения в случае, когда приложение всегда делает это. Итак, да, вам нужно иметь кеширование операторов c3p0 do.

Надеюсь, это поможет, извините, это немного затянуто. Ответ да .

2 голосов
/ 23 июня 2010

Помните, что операторы должны кэшироваться для соединения , что будет означать, что вам придется использовать довольно много памяти, и пройдет много времени, прежде чем вы увидите какую-либо выгоду. Так что если вы установите для него 100 кэшируемых операторов, то это фактически 100 * количество соединений или 100 / нет соединений, но вам все равно потребуется некоторое время, чтобы кэш-память имела какой-либо значимый эффект.

...