Форум программистов, компьютерный форум, киберфорум
Java: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/25: Рейтинг темы: голосов - 25, средняя оценка - 4.88
0 / 0 / 0
Регистрация: 15.03.2016
Сообщений: 135

Получение и обработка данных из большой таблицы (200 млн строк)

09.07.2018, 14:12. Показов 5411. Ответов 7
Метки c, jd, jdbc, mysql (Все метки)

Студворк — интернет-сервис помощи студентам
У меня есть большая таблица MySQL с порядка 200 млн записей.

Я делаю такой запрос, используя JDBC:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public List<Pair<Long, String>> getUsersAll() throws SQLException {
        Connection cnn = null;
        CallableStatement cs = null;
        ResultSet rs = null;
        final List<Pair<Long, String>> res = new ArrayList<>();
        try {
            cnn = dataSource.getConnection();
            cs = cnn.prepareCall("select UserPropertyKindId, login from TEST.users;");
            rs = cs.executeQuery();
            while (rs.next()) {
                res.add(new ImmutablePair<>(rs.getLong(1), rs.getString(2)));
            }
            return res;
        } catch (SQLException ex) {
            throw ex;
        } finally {
            DbUtils.closeQuietly(cnn, cs, rs);
        }
    }

Дальше я должен обработать результат:

Java
1
2
3
4
5
6
7
List<Pair<Long, String>> users= dao.getUsersAll();
            if (CollectionUtils.isNotEmpty(users)) {
                for (List<Pair<Long, String>> partition : Lists.partition(users, 2000)) {
                    InconsistsUsers.InconsistsUsersCallable callable = new InconsistsUsers.InconsistsUsersCallable (new ArrayList<>(partition));
                    processExecutor.submit(callable);
                }
            }
Так как таблица очень большая и все данные выгружаются в память, падает с ошибкой:

Java
1
2
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 105,619 milliseconds ago.
Как я могу получать данные частями, что не выгружать сразу все в память. Может быть использовать курсор и складывать данные в какую-нибудь неблокирующую очередь и по мере прихода в нее данных их разгребать? Как это лучше сделать?

Структуру базы я менять не могу, все манипуляции нужно сделать из Java кода.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
09.07.2018, 14:12
Ответы с готовыми решениями:

Получение данных из textBox с свойством multiline с разных строк в разные поля таблицы
Никак не пойму как сделать что бы в бд добавлялись данные с каждой строки textbox с multiline в разные поля таблицы.Пишу на на C#.

Работа с большой базой (>1 млн записей)
Товарищи, помогите! Я недавно перешел на C# 2005, меня особенно интересует вопрос работы с большими базами (более 1 млн. записей) В...

Редактирование таблицы: разрешено редактировать только 200 строк
Извините за беспокойство. Прошу помощи.С Microsoft SQL Server 2008 никогда не работал. Знал бы как не спрашивал. Дело в чём есть БД...

7
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,765
09.07.2018, 14:25
Цитата Сообщение от Neo-X2006 Посмотреть сообщение
Как я могу получать данные частями, что не выгружать сразу все в память.
Очевидно делать partition не в коде по коллекции, а в БД при запросе на получение данных.
0
0 / 0 / 0
Регистрация: 15.03.2016
Сообщений: 135
09.07.2018, 14:35  [ТС]
Цитата Сообщение от korvin_ Посмотреть сообщение
Очевидно делать partition не в коде по коллекции, а в БД при запросе на получение данных.
Тогда возникнет другая проблема с производительностью, тк на больших лимитах и оффсетах запрос будет выполнятся очень долго.
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,765
09.07.2018, 16:53
Цитата Сообщение от Neo-X2006 Посмотреть сообщение
Тогда возникнет другая проблема с производительностью, тк на больших лимитах и оффсетах запрос будет выполнятся очень долго.
Тогда производи манипуляции по мере чтения ResultSet'а, например

Java
1
2
3
4
5
@FunctionalInterface
public interface UserConsumer {
 
    void accept(long userPropertyKindId, String login) throws SQLException;
}
Java
1
2
3
4
5
6
7
8
public void getUsersAll(UserConsumer consumer) throws SQLException {
 
    ...
        while (rs.next()) {
            consumer.accept(rs.getLong(1), rs.getString(2));
        }
    ...
}
Или делай Stream поверх ResultSet'а (возможно, существуют готовые реализации), только закрывать connection, statement и rs нужно будет в методе close стрима.
0
0 / 0 / 0
Регистрация: 15.03.2016
Сообщений: 135
09.07.2018, 17:30  [ТС]
Цитата Сообщение от korvin_ Посмотреть сообщение
Тогда производи манипуляции по мере чтения ResultSet'а, например
А разве в данном случае, он вычитает не все сразу данные?

Java
1
2
3
while (rs.next()) {
            consumer.accept(rs.getLong(1), rs.getString(2));
        }
Насколько правильно сделать так:

Java
1
2
stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
Добавлено через 20 минут
Как вообще на стороне JDBC драйвера указать "Забирай данные пачками, по n элементов, а не грузи все сразу в паямять"?
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,765
09.07.2018, 20:31
Цитата Сообщение от Neo-X2006 Посмотреть сообщение
А разве в данном случае, он вычитает не все сразу данные?
Не обязательно, это зависит от драйвера и параметров Statement'а/ResultSet'а.

https://docs.oracle.com/javase... hSize-int-
https://docs.oracle.com/javase... hSize-int-

Цитата Сообщение от Neo-X2006 Посмотреть сообщение
Насколько правильно сделать так:

Java
1
stmt.setFetchSize(Integer.MIN_VALUE);
Вот так ни на сколько не правильно.

Цитата Сообщение от Neo-X2006 Посмотреть сообщение
"Забирай данные пачками, по n элементов, а не грузи все сразу в паямять"?
setFetchSize(n);

он и не грузит всё в память, он по-умолчанию работает с курсором. В зависимости от БД и драйвера, конечно.
Ты сам всё загружаешь сразу в память, в ArrayList.

Но вообще, с чего ты взял, что проблема в памяти?
com.mysql.jdbc.exceptions.jdbc4.Communic ationsException: Communications link failure
не выглядит как проблема с памятью.
0
0 / 0 / 0
Регистрация: 15.03.2016
Сообщений: 135
10.07.2018, 09:29  [ТС]
Цитата Сообщение от korvin_ Посмотреть сообщение
setFetchSize(n);
Насколько удалось понять отсюда https://dev.mysql.com/doc/conn... notes.html, из коробки в MySQL это не работает.

Цитата Сообщение от korvin_ Посмотреть сообщение
Но вообще, с чего ты взял, что проблема в памяти?
Мониторинг показал, что после запуска данной выгрузки, выжралась вся память на сервере.
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,765
10.07.2018, 10:58
Цитата Сообщение от Neo-X2006 Посмотреть сообщение
из коробки в MySQL это не работает.
Работает, только настроить надо, там же написано:

Another alternative is to use cursor-based streaming to retrieve a set number of rows each time. This can be done by setting the connection property useCursorFetch to true, and then calling setFetchSize(int) with int being the desired number of rows to be fetched each time:

Java
1
2
3
4
conn = DriverManager.getConnection("jdbc:mysql://localhost/?useCursorFetch=true", "user", "s3cr3t");
stmt = conn.createStatement();
stmt.setFetchSize(100);
rs = stmt.executeQuery("SELECT * FROM your_table_here");
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
10.07.2018, 10:58
Помогаю со студенческими работами здесь

Получение данных из текстового файла, чей вес от 200 Мб и больше
Здравствуйте, форумчане! Подскажите пожалуйста правильный метод получения текстовых данных в виде таблицы из текстового файла, где...

Создание большой таблицы из данных двух столбцов
Добрый день! Есть две достаточно большие колонки данных: примерно в 100 и в 1000 значений сответственно. Для загрузки в CRM нужно создать...

Обработка строк по условию, получение подстрок из строки! Консультация
Всем доброго времечка! Только начал изучать C#, так что сильно не пинать. Поставил себе для решения задачку: Имеем текстовый файл...

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

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а привычная функция main(). . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru