JDBC большой боров памяти? - PullRequest
0 голосов
/ 13 ноября 2009

Мне нужно многократно получать доступ (считывать) данные из базы данных в моих кодах Java, и поэтому я принял JDBC. Однако мне кажется, что использование JDBC отнимает много памяти. Я пытался быть осторожным с закрытием объектов, созданных для JDBC (ResultSet, Statemenet), но все же кажется, что он требует много памяти, особенно по сравнению с чтением ввода из текстового файла. Кто-нибудь знает лучший способ уменьшить потребление памяти? Благодарю.

Ответы [ 8 ]

4 голосов
/ 13 ноября 2009

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

JDBC не является ресурсоемким, поддерживается тем фактом, что вы можете запускать JDBC даже на мобильных устройствах с JavaME - средой с очень ограниченными ресурсами.

Поэтому, хотя вы, возможно, оцените более простую обработку данных в таких средах, как Hibernate или JPA, вам не следует беспокоиться о том, что JDBC потребляет любое количество ресурсов, которые стоит упомянуть в контексте всего приложения.

Как говорится: не пытайтесь оптимизировать вещи, которые не являются проблемой:)

3 голосов
/ 13 ноября 2009

JDBC не боров памяти. Данные, которые он возвращает, могут быть огромной памятью.

Одной из распространенных проблем с JDBC является то, что наборы результатов, которые содержат огромное количество данных (и не всегда оптимизированы для памяти), не обрабатываются или закрываются неправильно. Чтобы предотвратить утечки памяти из-за объекта ResultSet, разработчик должен предпринять осторожные шаги, чтобы убедиться, что память освобождена, прежде чем двигаться дальше. (Java обрабатывает большую часть очистки памяти, что означает, что это слепая зона для большинства разработчиков, поэтому это не удивительно.)

Рассмотрите возможность использования этого кода. Для окончательного закрытия результирующего набора используется шаблон «try / catch try / finally»:

try{
    Statement stmt = conn.createStatement();
    try {
        ResultSet rs = stmt.createQuery("some sql");
        try {
            // ResultSet processing goes here
        } finally {
            rs.close();
        }
    } finally {
        stmt.close();
    }
}
catch ( SQLException ex ) { // exception processing for any problems. }

Это гарантирует, что результирующий набор закрыт, даже если выдается исключение.

2 голосов
/ 10 марта 2011

Я бы хотел добавить важный момент, после того как сам столкнулся с проблемами с памятью:

Я читал большие наборы данных из базы данных MySQL (около 600 000 строк по 20 столбцов) и продолжал исчерпывать пространство кучи. Я думал, что смогу это исправить, изменив размер выборки, но установка размера выборки в PreparedStatement ничего не сделала.

Я обнаружил, что используемый мной драйвер JDBC MySQL (версия 5.1.15) не поддерживает размеры выборки. Фактически, для каждого запроса MySQL он загружает весь ResultSet в память. Однако, если вы установите размер выборки в Integer.MIN_VALUE, то драйвер будет загружать по 1 строке за раз с сервера MySQL .... с одной оговоркой: вы не можете выполнять любые другие операторы на соединении, пока ResultSet не будет закрыт.

Это задокументировано здесь:

http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html

При этом, если у вас есть контроль над сервером MySQL, вы можете установить для 'useCursorFetch' значение true, и сервер будет возвращать число строк defaultFetchSize вместо всех. Это верно с версии 5.0.2 MySQL. Разработчик утверждает, что это экспериментальный хак, поэтому будьте осторожны: http://forums.mysql.com/read.php?39,137457,137457#msg-137457

В любом случае, мораль этой истории в том, чтобы проверить используемый вами драйвер JDBC на наличие каких-либо особенностей.

2 голосов
/ 14 ноября 2009

Я должен согласиться с тем, что здесь говорили другие, что сам JDBC не использует большой объем памяти. Однако, если вас беспокоит конкретная операция JDBC, использующая много памяти, вы можете использовать либо JConsole, либо профилировщик, чтобы посмотреть, сколько кучи используется во время выполнения указанного метода.

2 голосов
/ 13 ноября 2009

Если вы когда-либо сталкивались с этой проблемой, то, вероятно, это ваш собственный код, который является проблемой памяти. Это может произойти, если вы перетащите все содержимое базы данных в память Java. Это на самом деле не вина JDBC.

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

Если вам действительно нужны все данные таблицы, то вы, вероятно, используете не тот инструмент с JDBC. Достойные серверы БД поставляются с более достойными инструментами импорта / экспорта для этого. Сначала посмотрите.

2 голосов
/ 13 ноября 2009

Маловероятно, что «JDBC» - это боров памяти. JDBC - это просто труба. Объем используемой памяти будет зависеть от того, с какой базой данных вы разговариваете, и, что более важно, с какими запросами вы работаете и правильно ли используете курсоры.

Вы можете обратиться к Hibernate за помощью в управлении использованием памяти при работе с большими объемами данных.

1 голос
/ 13 ноября 2009

Это больше фактор загрузки данных, чем библиотека JDBC. Поскольку вызовы JDBC включают в себя много данных, я бы проверил, что у вас не много объектов, которые сидят в коллекции, которая не была выпущена, и попадают в кучу второго поколения.

0 голосов
/ 13 ноября 2009

Один раз JDBC может использовать много памяти, если вы выполняете запросы, которые возвращают много строк из базы данных, и наборы результатов прокрутки не поддерживаются драйвером JDBC. Это приводит к тому, что все строки извлекаются с сервера и потенциально загружаются в ОЗУ.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...