Я использую весенний пакет для выполнения задания по переносу данных. данных много, поэтому я решил использовать JdbcPagingItemReader для чтения данных постранично. Ниже я определяю читателя:
private JdbcPagingItemReader<Map<String, Object>> buildItemReader(final DataSource dataSource, String tableName,
String tenant){
String tenantName = tenantHelper.determineTenant(tableName);
Map<String, Object> sqlParameterValues = new HashMap<>();
sqlParameterValues.put("tableName", tableName);
sqlParameterValues.put("tenantName", tenantName);
sqlParameterValues.put("tenant", tenant);
JdbcPagingItemReader<Map<String, Object>> itemReader = new JdbcPagingItemReader<>();
itemReader.setDataSource(dataSource);
itemReader.setPageSize(2);
itemReader.setFetchSize(2);
itemReader.setQueryProvider(generateSqlPagingQueryProvider(tableName,tenantName,tenant));
//itemReader.setParameterValues(sqlParameterValues);
itemReader.setRowMapper(new ColumnMapRowMapper());
try {
itemReader.afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
return itemReader;
}
private PostgresPagingQueryProvider generateSqlPagingQueryProvider(String tableName, String tenantName,
String tenant) {
PostgresPagingQueryProvider provider = new PostgresPagingQueryProvider();
Map<String, Order> sortKeys = new LinkedHashMap<>();
String sortKey = getSortKeyBytable(tableName);
sortKeys.put(sortKey, Order.ASCENDING);
provider.setSelectClause("select *");
provider.setFromClause("from " + tableName);
provider.setWhereClause("where " + tenantName + " ='" + tenant + "'");
provider.setSortKeys(sortKeys);
return provider;
}
ключ сортировки, который я указал, является первичным ключом в таблице, это строка. Но пейджинг не работает должным образом. Но он не выдает ошибки, он просто читает все данные.
В пакетном документе весны он предоставляет пример, который использует идентификатор типа int в качестве ключа сортировки, мне интересно, поддерживает ли только чтение весеннего пакетного пейджинга ключевое слово сортировки типа int? А может не поддерживать ключ сортировки строк?
Это ограничение весенней партии?




Это не ограничение весенней партии. Так работает база данных. Он сортирует строку на основе ее значения ascii.
Спасибо, сравнение строк сработало. Но пейджинг по-прежнему не работает для меня. Читатель просто считывает все данные в память.
Можете ли вы проверить запрос, сгенерированный весенним пакетом? Установить конфигурацию logging.level.org.springframework.batch.item.database=DEBUG
Ниже приведен запрос, сгенерированный весенним пакетом, я попробовал его в редакторе sql, это правильно, но память по-прежнему не освобождалась после каждого фрагмента: SELECT * FROM custom_amount WHERE (tenant_id = 'bf2e8407-5fa3-4137-9683- 75d4e95c8c6c') И ((id > '02B66704-3CA7-4B94-9678-7087305DA45E')) ORDER BY id ASC LIMIT 2
Память будет освобождена, т.е. gc будет запущена только тогда, когда будет использована почти вся выделенная память... Попробуйте уменьшить выделенную память до jvm..
да, я развертываю приложение, и если бы я не установил большой размер памяти, которую оно использует, оно просто не смогло бы завершить миграцию и выдало бы такую ошибку: исчерпание ресурсов; память кучи JVM не может быть выделена. И когда я отслеживаю процесс, я обнаружил, что он почти использует всю память, выделенную для приложения.
Вы используете базу данных в памяти для метаданных весеннего пакета? Какой репозиторий заданий вы используете?
Да, мы используем базу данных h2 для хранения пакетных данных Spring, таких как данные job_execution. Будет ли это первопричиной?
да, так как это со временем продолжает расширяться в памяти. Мы также столкнулись с подобной проблемой.
Я пытался не использовать базу данных памяти, но оказалось, что использование памяти по-прежнему очень высоко, это не должно быть основной причиной. Я уверен, что весенний пакет просто прочитал все данные в память.
Прежде чем делать поспешные выводы, попробуйте проанализировать использование памяти с помощью консоли кучи!
Спасибо, я пытаюсь проанализировать журналы gc и память кучи.
Пожалуйста, сообщите нам о своих выводах!
Привет Сим, Просто хочу поделиться с вами тем, что я нашел основную причину этой проблемы. Считыватель подкачки работал. Причина, по которой это не сработало, заключается в том, что я все еще вызываю средство чтения курсора на своем пакетном шаге. Это была моя вина, извините за путаницу и спасибо за вашу помощь.
Прекрасная работа! Рад, что вы нашли правильную первопричину в конце концов!
Пожалуйста, не забудьте проголосовать, если я вам чем-то помог.
Конечно, большое спасибо за помощь, Сим. Это действительно помогает
Приведенный выше код в вопросе действительно работал и решил мою проблему с памятью, причина, по которой он не работал, заключается в том, что я все еще вызываю Cursor Reader в своем определении шага весенней партии. Таким образом, программа чтения страниц может решить проблему с памятью.
Глядя на комментарий
the String compare did work. But the paging still not work for me. The reader just read all the data into the memory.: я думаю, что ваша проблема связана с stackoverflow.com/questions/55390995 (см. мой ответ там). Ключ сортировки может быть любого типа, и пейджинг работает нормально. Это ваш драйвер Postgresql, который загружает все данные в память.