powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / ConnectionPool + PreparedStatements, вопрос-дискуссия
8 сообщений из 8, страница 1 из 1
ConnectionPool + PreparedStatements, вопрос-дискуссия
    #38172310
BaurzhanS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет!

Пришла в голову идея скрестить ConnectionPool + PreparedStatements, но перед использованием хочу прояснить некоторые моменты. Оговорюсь, что все ниже написанное предполагает использование MySql.

Плюс использования пула- соединение создается не не при каждом запросе от клиента, а используется из пула. Подробности про создание нового, если нет свободных или ожидание свободного соединения я опущу, сейчас суть не в этом. Плюс использования PreparedStatements - помимо защиты от инъекций, использование этой штуки предотвращает синтаксический разбор и попытки движка оптимизировать запрос - то есть, если один и тот же запрос занимает 90% всех запросов в системе( как раз мой случай), можно его "запрепарировать" и избавиться от выполнения одних и тех же Действий движком СУБД.

Вопрос: когда мы делаем someConnection.prepareStatement("query"), созданный PreparedStatement хранится где-то в кэше СУБД или же в этом объекте - то есть, уничтожив этот объект, либо создавая каждый раз его заново, мы теряем его и в итоге все плюсы использования PS или же даже при уничтожении этого объекта движок СУБД понимает, что такой запрос уже был "запрепарирован" и не выполняет разбор+оптимизацию?

Если ответ да, СУБД хранит инфу о таких вещах и даже многократный вызов someConnection.prepareStatement("query") одного и того же запроса не вызывает повторной подготоки Statement-а, а вытаскивается из кеша тогда расходимся, мои дальнейшие рассуждения отпадают)

Если ответ нет, не хранит и для получения пользы от PreparedStatement, его нужно хранить и пользоваться впоследствии этим же объектом, тогда есть такие тезисы, которые я хотел бы обсудить, подвергнуть критике:

1) Храним в пуле не только соединения, но и PreparedStatement на самый частый, Bottle Neck запрос.

2) При запросе соединения из пула для выполнения какого-либо запроса передаем буллевый флаг - это Bottle Neck запрос или простой запрос. В первом случае пул пользуется подготовленным ранее PreparedStatement-ом, во втором случае просто делаем что-то вроде
Код: java
1.
2.
stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery(query);



3) Понятно, что если у Вас в системе нет очень частых однообразных запросов, тогда глупо использовать идею, приведенную выше - вы не почувствуете разницу от того, парсит ли движок СУБД ваш запрос каждый раз или нет, если он выполняется раз в день или раз в неделю, если это запрос,например, на генерацию отчета.

4) А что если у Вас десятки разных запросов и есть несколько Bottle Neck-ов? Если бы было 1-5 таких, можно было бы вместо буллевого флага передавать цифру - 1,2,3,4,5 - номер Bottle Neck, запроса или -1 - когда просто пользуемся соединением - кусочек кода из пункта 2. Но если Bottle Neck-ов 10-20 или более, не будете же Вы хардкодить все эти варианты и потом еще пистаь аццкий switch case вида
Код: java
1.
2.
3.
4.
5.
6.
7.
 public ResultSet executeQuery(String query, int type){
     swicth(type){
         case 1: return PS1.executeQuery(query);
         ...
         case 30: return PS30.executeQuery(query);
    }
}



Выход есть - В пуле теперь хранится вместо пары (Connection conn, PreparedStatement bottleNeck) пара (Connection conn, HashSet<String,PreparedStatement> bottleNecks) - то есть при выполнение запроса смотрим, есть ли он в сете, если нет - это простой запрос, если есть - вытаскиваем из сета и пользуемся.

Но как создавать/инициализировать этот сет? Создаем файл с тестом наших Bottle Neck запросов, естественно оформляя подставляемые параметры как "?", и в конструкторе объекта пула считываем с файла и "препарим" их.

Собственно все, хотелось бы услышать конструктивную критику, идеи для дальнейшего улучшения либо опыт использования такой конструкции, если таковой был.
...
Рейтинг: 0 / 0
ConnectionPool + PreparedStatements, вопрос-дискуссия
    #38172369
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BaurzhanS Если ответ да, СУБД хранит инфу о таких вещах и даже многократный вызов someConnection.prepareStatement("query") одного и того же запроса не вызывает повторной подготоки Statement-а, а вытаскивается из кеша тогда расходимся, мои дальнейшие рассуждения отпадают)

СУБД кеширует по тексту запроса его план и повторно не парсит SQL, если запрос 1-в-1 совпадает.
Смысла кешировать экземпляры при наличии young generation в GC особого нет.
Чем рассуждать, можно было написать тестовый пример и посмотреть, будет ли какая-то выгода, или нет.
...
Рейтинг: 0 / 0
ConnectionPool + PreparedStatements, вопрос-дискуссия
    #38172652
Йуный джавистЪ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пришла в голову идея скрестить ConnectionPool + PreparedStatements
Уже реализовали такую идею, почитайте документацию по имеющимся пулам.
Вообще, в случае mysql вы ускорения не добьетесь, потому что парсер там быстр а оптимизатор туп (это не оракл).
...
Рейтинг: 0 / 0
ConnectionPool + PreparedStatements, вопрос-дискуссия
    #38172654
Йуный джавистЪ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
СУБД кеширует по тексту запроса его план и повторно не парсит SQL, если запрос 1-в-1 совпадает.
В постгресе и mysql после подготовки запроса сервер выдает id подготовленного запроса. Клиент должен запомнить этот id. В оракле конечно удобнее сделано.
...
Рейтинг: 0 / 0
ConnectionPool + PreparedStatements, вопрос-дискуссия
    #38172673
BaurzhanS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz, насчет Blazkowiczповторно не парсит SQL, если запрос 1-в-1 совпадает. - имеется в виду что даже подставляемые параметры должны совпадать, например select * from ttt where x=111 и select * from ttt where x=222, это одинаковые запросы?
...
Рейтинг: 0 / 0
ConnectionPool + PreparedStatements, вопрос-дискуссия
    #38172696
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BaurzhanSBlazkowicz, насчет Blazkowiczповторно не парсит SQL, если запрос 1-в-1 совпадает. - имеется в виду что даже подставляемые параметры должны совпадать, например select * from ttt where x=111 и select * from ttt where x=222, это одинаковые запросы?
Имеется ввиду, что если вместо binding variables
Код: sql
1.
select * from names where id = ?


инлайнить параметры
Код: sql
1.
select * from names where id = 1


то СУБД не сможет кешировать такие запросы, а будет каждый раз их парсить и составлять план запроса. Возможно это где-то уже решается. Но это больше вопрос к реализации СУБД. В общем случае так делать не стоит.
...
Рейтинг: 0 / 0
ConnectionPool + PreparedStatements, вопрос-дискуссия
    #38172703
Йуный джавистЪ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
СУБД не сможет кешировать такие запросы, а будет каждый раз их парсить и составлять план запроса

В оракле для этого есть cursor_sharing=force
...
Рейтинг: 0 / 0
ConnectionPool + PreparedStatements, вопрос-дискуссия
    #38172717
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Йуный джавистЪВ оракле для этого есть cursor_sharing=force
Да, понятно, что это технически решаемо. Но запрос всё равно парсится чтобы идентифицировать литералы, которые можно заменить на параметры. Опять же, то Oracle. А все ли так умеют?
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / ConnectionPool + PreparedStatements, вопрос-дискуссия
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]