Как стать автором
Обновить

Комментарии 21

Я всегда думал, что в современных СУБД по умолчанию включён функционал пула соединений, и свой огород городить не нужно.
На стороне СУБД просто есть функционал открытия соединений и обработки запросов, а как Вы будете его использовать эти функции уже зависит от Вас. Если просто когда надо открывать соединение и когда получили результат закрывать, то будут проблемы с производительностью.
Если честно ожидал увидеть сравнение пулов: c3po, bonecp, apache commons, tomcat (у них какой то свой). То что надо кэшировать и так всем понятно.
В данной статье я ставил целью показать, что существует такая проблема, зачастую многие не могут ответить на вопрос: зачем нужны пулы соединений. А так же показать, что писать самому реализацию кеширования не имеет смысла. Сравнение уже существующих реализация можно провести, но мне кажется, что там результаты тестов не будут сильно различаться.
Тоже вариант. Есть маленькое пожелание для более простого понимания: выделите жирным, что кэшировать надо, и что писать свои пулы не надо и что PGPoolingDataSource использовать не надо если уже есть другой пулл.
В данной статье я ставил целью показать, что существует такая проблема
У кого как, лично у меня сложилось впечатление, что статью надо было писать лет 10 назад, а то и больше. Тогда у "проблемы" пула соединений с БД была некая актуальность. Сейчас в большинстве движков/фреймворков/серверов приложений такие вещи включены по-умолчанию. Если крутануть лет на 5-7 (а не на 10) назад, то актуальными были уже кэширование запросов и результатов выборки. Опять же, сейчас это есть почти везде и делается просто путем указания в конфигурации флага включить/выключить. В наше время интересными темами являются вопросы распределенных кэшей.
>Первый шаг открытия соединения с сервером, является довольно долгим и мы можем его исключить заранее подготовив пул уже открытых соединений и предоставляя из него соединения приложению по мере необходимости.

pgbouncer же.
Пулы соединений на стороне приложения хороши тогда, когда веб-серверов мало, и мало серверов баз данных. А вот когда у вас 100 веб-серверов и 100 серверов баз данных, причём каждый веб-сервер может обращаться к любой базе, даже при размере пула в 1 соединение мы получим 100 «висящих» соединений на каждом сервере баз данных. Поэтому правильно вам говорят про отдельные прокси-сервера типа pgbouncer, которые за вас держат коннекты ко всем серверам, а вы к ним только обращаетесь
Но даже в таком случае следует на стороне веб-сервера держать пул соединений к pgbouncer
Тему статьи можно переформулировать так «Одна из причин почему в проекте надо использовать популярный|проверенный фреймворк». При использовании фреймворка, согласен на первом этапе может быть некоторый оверворк, но когда реально встанет вопрос с проблемами расширения|масштабирования, уже будет понятно есть ли на это деньги и мотивация.)
У меня вопрос: объект PreparedStatement привязан к Connection или нет? Иными словами, можно ли использовать один prepared statement с разными connection? Или при создании prepared statement на стороне сервера создаётся какое-то состояние?
Не нашел там ответа на свой вопрос.
Да PreparedStatement связан с объектом Connection, который его создал. Именно по этому в самописном пуле кеширование происходит в классе Connection
   public PreparedStatement prepareStatement(String sql) throws SQLException {
            PreparedStatement statement = statements.get(sql);
            if (statement == null) {
                statement = new MyStatement(connection.prepareStatement(sql));
                statements.put(sql, statement);
            }
            return statement;
        }

немного удивлен олдскульному синтаксису. Вы пробовали java 7?
Не очень понял про синтаксис. Можете прояснить что Вам не понравилось?
ну почти, в данном случае интерфейс AutoCloseable не очень подходит, я фишки Project Coin как например Diamond operator (http://stackoverflow.com/questions/4166966/what-is-the-point-of-the-diamond-operator-in-java-7) которые можно было бы использовать. Использование JDBC 4 тоже делает код немного прозрачнее
AutoClosable очень кстати для первого листинга, там finally на пол-программы
У вас слишком мало тестовых данных чтобы делать серёзные выводы.
Нужно значительно больше данных, ваш объём вообще влезает в одну страницу и ещё очень много места останется, которая самой СУБД скорее всего прокешируется в памяти, кроме того план иссполнения будет самый примитивный.
Самой большой проблемой и очень частым запросом в реальных приложениях идёт JOIN и очень часто проседание в производительности имеено здесь. Потому тэст стоило делать с JOIN.
А теперь добави сюда влияние индексов, а также тот факт что для различного количества данных СУБД может и будет исспользовать разные планы иссполнения, то мы поймём что писать свой самописный кеш не стоит, только если вы не съели зубы на даном движке СУБД и имеете очень хороший опыт в реализации. Да кстати то что работало у вас сегодна, может сломаться завтра на новой версии СУБД.
Кажется тестировалась не производительность запросов, а издержки при постоянном открытии новых соединений. По моему достаточно показательно.

А насчет планов, я больше скажу — насколько я понял, в рамках одного PreparedStatement план не будет корректироваться относительно изменения статистики в базе (поправьте меня, если кто в курсе). Поэтому в навороченных движках также есть настройка времени жизни (TTL) Connection и PreparedStatement. Иначе может получиться, что система тормозит — нехватает индекса, создаешь его, а тормоза продолжаются, так как план устарел и не учитывает индекс. Если не предусмотрен TTL или хотя бы ручное закрытие соединений, то придется приложение перегрузить.

Так что да, самому писать такой велосипед себе дороже.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации