Самый быстрый способ выполнить итерации через большую таблицу с помощью JDBC

Большое предостережение - в моем офисе мы обнаружили, что (на некоторых компьютерах с Windows) мы не можем выделить более 512 м для кучи Java. Это связано с тем, что на некоторых из этих компьютеров установлен антивирус Касперского. После удаления этого AV-продукта мы обнаружили, что можем выделить как минимум 1,6 ГБ, т. Е. -Xmx1600m (m обязательно, иначе это приведет к другой ошибке «Слишком маленькая начальная куча»).

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

21
задан Ish 3 July 2009 в 21:13
поделиться

3 ответа

Прежде всего, вы уверены, что вам нужна вся таблица в памяти? Возможно, вам стоит рассмотреть (если возможно) выбор строк, которые вы хотите обновить / объединить / и т. Д. Если вам действительно нужна вся таблица, вы можете использовать прокручиваемый ResultSet. Вы можете создать его следующим образом.

// make sure autocommit is off (postgres)
con.setAutoCommit(false);

Statement stmt = con.createStatement(
                   ResultSet.TYPE_SCROLL_INSENSITIVE, //or ResultSet.TYPE_FORWARD_ONLY
                   ResultSet.CONCUR_READ_ONLY);
ResultSet srs = stmt.executeQuery("select * from ...");

Он позволяет вам переходить к любой строке, которую вы хотите, используя «абсолютные» и «относительные» методы.

21
ответ дан 29 November 2019 в 21:41
поделиться

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

  • ваша сеть (или, по крайней мере, ваше соединение с mysql) очень медленная? Вы можете попробовать запустить процесс локально в окне mysql, если это так, или на чем-то более подключенном.

  • есть ли что-то в структуре таблицы, которое его вызывает? вытаскивает 10к данных для каждой строки? 200 полей? вычисление значений идентификатора для получения на основе неиндексированной строки? Вы можете попробовать найти более удобный для БД способ извлечения данных (например, только те столбцы, которые вам нужны, иметь агрегированные значения БД и т. Д.)

Если вы ' re не проходит второе приращение, что-то действительно не так - эффективно или нет, у вас не должно возникнуть проблем с сбросом 2000 или 20 000 строк в память на работающей JVM. Может быть, вы храните данные избыточно или крайне неэффективно?

2
ответ дан 29 November 2019 в 21:41
поделиться

Мне помогло Statement.setFetchSize (Integer.MIN_VALUE) . Я почерпнул эту идею из блога Джейсона . Это сократило время выполнения более чем вдвое. Объем используемой памяти резко сократился (поскольку одновременно читается только одна строка).

Однако этот трюк не работает для PreparedStatement .

2
ответ дан 29 November 2019 в 21:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: