Pull to refresh

Comments 21

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

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

Так что да, самому писать такой велосипед себе дороже.
Sign up to leave a comment.

Articles