По умолчанию драйвер Postgres JDB C начинает использовать операторы на стороне сервера только после того, как подготовленный оператор используется 5 раз. Из документации по свойствам драйвера JDB C :
prepareThreshold = int
Определите количество выполнений PreparedStatement, необходимых перед переключением на использование подготовленных операторов на стороне сервера , Значение по умолчанию - пять, что означает начало использования подготовленных операторов на стороне сервера при пятом выполнении того же объекта PreparedStatement. Дополнительная информация о подготовленных инструкциях на стороне сервера доступна в разделе «Готовые операторы сервера».
Но это свойство можно изменить.
Это программа, с которой я тестировал:
Properties props = new Properties();
props.setProperty("user", "test");
props.setProperty("password", "test");
props.setProperty("loggerLevel", "TRACE");
props.setProperty("prepareThreshold", "1");
try (Connection con = DriverManager.getConnection("jdbc:postgresql:test", props);
PreparedStatement stat = con.prepareStatement("select * from app_user where username = ?"))
{
for (String username : List.of("user1", "user2", "user3"))
{
stat.setString(1, username);
try (ResultSet rs = stat.executeQuery())
{
if (rs.next())
System.out.println("User " + username + " has ID: " + rs.getString(1));
}
}
}
Когда для prepareThreshold
установлено значение 1
, журналы показывают:
Feb 18, 2020 1:56:59 PM org.postgresql.core.v3.QueryExecutorImpl execute
FINEST: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@33065d67, maxRows=0, fetchSize=0, flags=16
Feb 18, 2020 1:56:59 PM org.postgresql.core.v3.QueryExecutorImpl sendParse
FINEST: FE=> Parse(stmt=S_1,query="select * from app_user where username = $1",oids={1043})
Feb 18, 2020 1:56:59 PM org.postgresql.core.v3.QueryExecutorImpl sendBind
FINEST: FE=> Bind(stmt=S_1,portal=null,$1=<'user1'>)
Feb 18, 2020 1:56:59 PM org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
FINEST: FE=> Describe(portal=null)
Feb 18, 2020 1:56:59 PM org.postgresql.core.v3.QueryExecutorImpl sendExecute
FINEST: FE=> Execute(portal=null,limit=0)
...
Feb 18, 2020 1:56:59 PM org.postgresql.core.v3.QueryExecutorImpl execute
FINEST: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@35dab4eb, maxRows=0, fetchSize=0, flags=16
Feb 18, 2020 1:56:59 PM org.postgresql.core.v3.QueryExecutorImpl sendBind
FINEST: FE=> Bind(stmt=S_1,portal=null,$1=<'user2'>)
Feb 18, 2020 1:56:59 PM org.postgresql.core.v3.QueryExecutorImpl sendExecute
FINEST: FE=> Execute(portal=null,limit=0)
...
Feb 18, 2020 1:56:59 PM org.postgresql.core.v3.QueryExecutorImpl execute
FINEST: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@2d901eb0, maxRows=0, fetchSize=0, flags=16
Feb 18, 2020 1:56:59 PM org.postgresql.core.v3.QueryExecutorImpl sendBind
FINEST: FE=> Bind(stmt=S_1,portal=null,$1=<'user3'>)
Feb 18, 2020 1:56:59 PM org.postgresql.core.v3.QueryExecutorImpl sendExecute
FINEST: FE=> Execute(portal=null,limit=0)
, которые показывают, что анализ запроса происходит один раз, затем повторяются привязки.
Сравните это с тем, когда prepareThreshold
не установлено:
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl execute
FINEST: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@33065d67, maxRows=0, fetchSize=0, flags=17
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendParse
FINEST: FE=> Parse(stmt=null,query="select * from app_user where username = $1",oids={1043})
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendBind
FINEST: FE=> Bind(stmt=null,portal=null,$1=<'user1'>)
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
FINEST: FE=> Describe(portal=null)
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendExecute
FINEST: FE=> Execute(portal=null,limit=0)
...
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl execute
FINEST: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@8519cb4, maxRows=0, fetchSize=0, flags=17
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendParse
FINEST: FE=> Parse(stmt=null,query="select * from app_user where username = $1",oids={1043})
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendBind
FINEST: FE=> Bind(stmt=null,portal=null,$1=<'user2'>)
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
FINEST: FE=> Describe(portal=null)
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendExecute
FINEST: FE=> Execute(portal=null,limit=0)
...
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl execute
FINEST: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@35dab4eb, maxRows=0, fetchSize=0, flags=17
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendParse
FINEST: FE=> Parse(stmt=null,query="select * from app_user where username = $1",oids={1043})
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendBind
FINEST: FE=> Bind(stmt=null,portal=null,$1=<'user3'>)
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
FINEST: FE=> Describe(portal=null)
Feb 18, 2020 2:01:25 PM org.postgresql.core.v3.QueryExecutorImpl sendExecute
FINEST: FE=> Execute(portal=null,limit=0)
, где есть 3 отдельных анализа и связывания операторов. Однако после 5 запросов они должны начать использоваться повторно.
Что касается режима запросов «простой» или «расширенный», то, похоже, журналы всегда выводят «простой запуск» независимо от различий. В этом простом режиме параметры не будут связаны в подготовленном операторе, и вместо этого весь запрос будет отправлен в виде текста. В этом примере, если для свойства preferQueryMode
установлено значение simple
, журналы показывают:
Feb 18, 2020 2:06:19 PM org.postgresql.core.v3.QueryExecutorImpl execute
FINEST: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@33065d67, maxRows=0, fetchSize=0, flags=1,041
Feb 18, 2020 2:06:19 PM org.postgresql.core.v3.QueryExecutorImpl sendSimpleQuery
FINEST: FE=> SimpleQuery(query="select * from app_user where username = 'user1'")
...
Feb 18, 2020 2:06:20 PM org.postgresql.core.v3.QueryExecutorImpl execute
FINEST: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@28261e8e, maxRows=0, fetchSize=0, flags=1,041
Feb 18, 2020 2:06:20 PM org.postgresql.core.v3.QueryExecutorImpl sendSimpleQuery
FINEST: FE=> SimpleQuery(query="select * from app_user where username = 'user2'")
...
Feb 18, 2020 2:06:20 PM org.postgresql.core.v3.QueryExecutorImpl execute
FINEST: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@d737b89, maxRows=0, fetchSize=0, flags=1,041
Feb 18, 2020 2:06:20 PM org.postgresql.core.v3.QueryExecutorImpl sendSimpleQuery
FINEST: FE=> SimpleQuery(query="select * from app_user where username = 'user3'")
заметить разницу между этим и значением по умолчанию - нет параметров и 'user1', ' Значения user2 'и' user3 'отправляются в строке с каждым запросом.
Я думаю, что вам действительно нужно, чтобы немедленно повторно использовать операторы на стороне сервера и повторно привязать параметры. В этом случае установка prepareThreshold
на 1
сделает работу.