Пул соединений с JDBC все еще улучшает производительность в настоящее время?

Мое приложение не использует какие-либо формы пула соединений, я работаю напрямую с соединениями. Приложение выполняет в основном короткие простые запросы. Из журнала я вижу, что он часто открывает и закрывает соединения, часто выполняя только один выбор из одной или нескольких строк между ними. Обычно это занимает ~ 100 мс (включая открытие и закрытие соединения).

Существует бесчисленное количество статей и записей в блогах о том, как пул соединений улучшает производительность приложений, но все они кажутся довольно старыми (5 или более лет).

Обеспечивает ли пул соединений разумный выигрыш в производительности или он устарел. Я использую SQLServer 2008 с драйвером Microsoft JDBC версии 3.0, если это важно.


Результаты / Обновление: С тех пор, как я задал этот вопрос, произошло много событий (мы переключаем драйвер JDBC и многое другое). В свое время я провел множество рефакторингов и прочего, и в этом случае я также добавил в это приложение пул соединений. При объединении соединений в пул некоторые запросы теперь выполняются быстрее, чем можно измерить с помощью детализации временных меток журнала (я полагаю, менее 16 мс).

Итак, в заключение, да, объединение пулов по-прежнему стоит усилий, если вам нужно часто подключаться / отключаться.


person Durandal    schedule 01.07.2011    source источник


Ответы (2)


Если вам подходит 100 мс на запрос, тогда вам не нужен пул соединений. Если вам нужны запросы продолжительностью менее 20 мс, важно повторно использовать соединения.

Если ваш драйвер поддерживает собственный пул подключений, я предлагаю вам использовать его (в случае, если он еще не делает этого за вас). Только если вам нужен больший контроль над тем, как объединяются в пулы, вы можете использовать дополнительную библиотеку (я никогда не нашел хорошего применения для одной)

Примечание: вам не нужно использовать пул для повторного использования соединений.

Один простой способ повторно использовать соединения - иметь одно постоянное соединение (которое имеет соответствующие средства защиты потоков). Если ваши запросы нечасты, это может быть все, что вам нужно.

Если вы хотите иметь возможность выполнять запросы одновременно и иметь только несколько потоков, которые будут выполнять запросы, вы можете сохранить соединение в поле ThreadLocal.

Если вам нужно несколько подключений и у вас есть больше потоков, которые могут выполнять запрос, чем вы хотите иметь в подключениях, используйте пул.

Для модели ThreadLocal вы можете сделать

public static final ThreadLocal<Connection> CONNECTION = new ThreadLocal<Connection>() {
     public Connection initialValue() {
         LOG.info(Thread.currentThread()+": created a connection.");
         return createConnection();
     }
};

Если вы хотите контролировать, как очищаются соединения.

private static final Map<Thread, Connection> connections = new ConcurrentHashMap();
public static final ThreadLocal<Connection> CONNECTION = new ThreadLocal<Connection>() {
     public Connection initialValue() {
         LOG.info(Thread.currentThread()+": created a connection.");
         Connection conn = createConnection();
         connections.put(Thread.currentThread(), conn);
         return conn;
     }
};
public static void cleanUp() {
     for(Map.Entry<Thread, Connection> entry: connections.entrySet()) {
         Thread t = entry.getKey();
         if (!t.isAlive()) {
             LOG.info(t+": closed a connection.");
             connections.remove(t);
             entry.getValue().close();
         }
     }
}

Если вас беспокоит обрыв соединения, вы можете переопределить get () ThreadLocal, чтобы проверить соединение перед возвратом.

person Peter Lawrey    schedule 01.07.2011
comment
Одно постоянное соединение не будет работать, но количество потоков, выполняющих запросы, ограничено (я думаю, что в настоящее время он установлен на 2xCPUS). В моем случае идею ThreadLocal можно было бы достаточно легко реализовать, хотя при завершении работы их было бы трудно закрыть. На данный момент у меня нет серьезных проблем с производительностью со временем соединения, но это может измениться, когда клиент будет более широко использоваться. - person Durandal; 01.07.2011
comment
Как часто вы закрываете потоки? Можете ли вы сохранить статическое количество потоков? Если нет, у вас может быть набор Map<Thread, Connection>, который используется для поиска соединений мертвых потоков и закрытия их соединений. - person Peter Lawrey; 01.07.2011
comment
Потоки закрываются только при перезапуске или завершении службы, запускающей серверную часть, то есть при выходе из JVM. Думаю, на практике меня не убьет, если я никогда не уберу эти связи. Количество потоков определяется при запуске, сервер выбирает случайный неактивный поток и заставляет его выполнять любую требуемую услугу. Моя единственная проблема заключается в том, что этот пул потоков поддерживается не моим приложением, а некоторой структурой (которую я должен осторожно трогать, поскольку она также используется другими приложениями). - person Durandal; 01.07.2011
comment
Когда вы выключаете сервер, закрываете ли вы соединения сейчас явно? например если вы используете соединение? Когда вы закрываете приложение, все его TCP-соединения закрываются ОС (возможно, не так чисто) - person Peter Lawrey; 01.07.2011
comment
На сервере есть несколько хуков выключения, которые вызывают некоторые хуки очистки в моем коде, но я действительно не могу гарантировать, что все закрыто должным образом (но я не могу думать ни о чем в своей голове это не так). Однако случилось так, что виртуальная машина не отключилась добровольно в производственной среде, предположительно из-за того, что все еще оставались активные потоки, которые отказывались завершиться должным образом. Примерно через 60 секунд оболочка службы принудительно завершила работу виртуальной машины. Мы не заметили каких-либо неблагоприятных воздействий на нашу базу данных. - person Durandal; 01.07.2011
comment
Я привел пример того, как вы можете сделать это в любом случае. Надеюсь, вы видите, что первый пример довольно прост. ;) - person Peter Lawrey; 01.07.2011
comment
Кроме того, независимо от задержки, некоторые серверы СУБД тратят много усилий на настройку вашего соединения. Таким образом, даже если задержка не важна для каждого клиента, вы причините серверу БД некоторую боль, которую легко избежать. - person jasonk; 19.06.2012

В некоторой степени это зависит от программного обеспечения базы данных. Некоторые (например, MySQL) имеют относительно легкие соединения, которые открываются быстро. Другие, такие как Oracle, имеют соединения, которые представляют собой большие сигнальные структуры с серьезными накладными расходами.

В целом, однако, рекомендуется использовать пул соединений, особенно для быстрых, коротких и объемных запросов. Чем быстрее ваше приложение будет содержать связи, тем оно станет важным. Это не изменилось за последние несколько лет - во всяком случае, это важнее, чем когда-либо, по мере того, как приложения расширяются и становятся более сложными.

Если вам нужно что-то убедительное, я предлагаю вам провести сравнительный анализ с объединением и без него. Если вы не получаете повышения производительности в вашем конкретном случае, возможно, это не стоит того.

person skaffman    schedule 01.07.2011