Повторное использование Postgres подготовленной выписки - PullRequest
1 голос
/ 05 мая 2020

Я смотрел на этот вопрос Повторное использование PreparedStatement несколько раз

Допустим, у меня есть две версии кода. Первый закрывает PreparedStatement после каждого использования внутри for l oop.

connection.autoCommit(false)    
for (int i=0; i<1000; i++) {
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setObject(1, someValue);
        preparedStatement.executeQuery();
        preparedStatement.close();    // ? Close after each use.
    }
    connection.commit();
    connection.close();

В этом втором примере PreparedStatement остается открытым для повторного использования, чтобы закрыть позже после the for l oop.

connection.autoCommit(false)
PreparedStatement preparedStatement = connection.prepareStatement(sql);
for (int i=0; i<1000; i++) {
    preparedStatement.clearParameters();
    preparedStatement.setObject(1, someValue);
    preparedStatement.executeQuery();
}
preparedStatement.close();           // ? Close after repeated uses.
connection.commit();
connection.close();

Как видите, я создаю и закрываю PS в l oop или повторно использую тот же PS. Я использую postgres и согласно документации

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

Как я понимаю, если я использую postgres, то два приведенных выше примера будут обрабатываться одинаково, потому что они выполняются в одной транзакции. Так, например, в первом примере кода с новым оператором внутри l oop, postgres создаст единый планировщик для оператора, и даже если мы закроем оператор и создадим новый в l oop postgres, будет повторно использоваться кешированный, потому что это происходит в том же сеансе (транзакции), и этот кешированный планировщик будет удален только тогда, когда транзакция будет зафиксирована (connection.commit()). Я прав ?

1 Ответ

2 голосов
/ 05 мая 2020

Продолжительность подготовленного оператора длится в течение сеанса базы данных, который отличается от транзакции (сеанс завершается, когда клиент отключается, тогда как транзакция заканчивается - обычно- с помощью COMMIT или ROLLBACK).

создание одного или нескольких планов зависит, по крайней мере, от следующего (это ПОДГОТОВИТЕЛЬНОЕ ЗАЯВЛЕНИЕ, которое генерирует план):

Подготовленный оператор может быть выполнен с помощью любого generi c план или план индивидуальный . Общий план c одинаков для всех выполнений, в то время как настраиваемый план создается для конкретного выполнения c с использованием значений параметров, указанных в этом вызове. Использование общего плана c позволяет избежать накладных расходов на планирование, но в некоторых ситуациях индивидуальный план будет гораздо более эффективным для выполнения, поскольку планировщик может использовать информацию о значениях параметров. (Конечно, если подготовленный оператор не имеет параметров, это спорный вопрос, и всегда используется общий план c.)

По умолчанию (то есть, когда plan_cache_mode установлен на auto), сервер автоматически выберет, использовать ли общий c или индивидуальный план для подготовленного оператора с параметрами. Текущее правило для этого состоит в том, что первые пять выполнений выполняются с пользовательскими планами, и рассчитывается средняя оценочная стоимость этих планов. Затем создается общий план c, и его ориентировочная стоимость сравнивается со средней стоимостью индивидуального плана. При последующих выполнениях используется общий план c, если его стоимость не настолько выше, чем средняя стоимость индивидуального плана, чтобы сделать повторное перепланирование более предпочтительным. 1018 *PREPARE команда]

...