Подтвердить что ты не робот

Должен ли я активировать сборку команд c3p0?

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

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

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

В настоящий момент мы имеем

 c3p0.maxStatements = 0
 c3p0.maxStatementsPerConnection  =   0

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

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

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

Right?

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

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

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

Итак: разумно ли активировать maxStatementsPerConnection с c3p0 и Postgresql? Есть ли реальные выгоды, активизирующие его?

С уважением Janning

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

Ответ 2

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