Запись большого ResultSet в файл - PullRequest
6 голосов
/ 25 августа 2011

Я пытаюсь записать большой ResulSet (~ 1 мм строк) в один файл. Есть ли предпочтительный / эффективный способ сделать это в Java 1.6?

Ответы [ 2 ]

13 голосов
/ 25 августа 2011

Это зависит от используемого драйвера JDBC.Вам нужно дать указание драйверу JDBC , а не загружать весь ResultSet в память Java заранее, а вместо этого загружать его для каждой строки при каждом вызове next().Затем, внутри цикла ResultSet#next(), вам нужно записать данные немедленно в файл вместо того, чтобы хранить его в List или что-то в этом роде.

Непонятно, какой драйвер JDBC вы используетеиспользуя, но, например, драйвер JDBC MySQL может быть проинструктирован для обслуживания набора результатов для каждой строки следующим образом согласно документации драйвера JDBC MySQL :

ResultSet

По умолчанию ResultSets полностью извлекается и сохраняется в памяти.В большинстве случаев это наиболее эффективный способ работы, и благодаря конструкции сетевого протокола MySQL его проще реализовать.Если вы работаете с ResultSets, которые имеют большое количество строк или больших значений и не могут выделить пространство кучи в JVM для требуемой памяти, вы можете указать драйверу потоковую передачу результатов назад по одной строке за раз.

Чтобы включить эту функцию, вам нужно создать экземпляр Statement следующим образом:

 stmt = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
 stmt.setFetchSize(Integer.MIN_VALUE);

Вот конкретный пример запуска:

try (
    PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("/records.txt")), "UTF-8"));
    Connection connection = dataSource.getConnection();
    Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
) {
    statement.setFetchSize(Integer.MIN_VALUE);

    try (ResultSet resultSet = statement.executeQuery("SELECT col1, col2, col3 FROM sometable")) {
        while (resultSet.next()) {
            writer.append(resultSet.getString("col1")).append(",")
                  .append(resultSet.getString("col2")).append(",")
                  .append(resultSet.getString("col3")).println();
        }
    }
}

КстатиЯ бы сначала проверил, не имеет ли БД встроенную поддержку SQL для этого, что может сделать это намного эффективнее.Например, MySQL имеет для этого SELECT INTO OUTFILE конструкцию .

Форма SELECT ... INTO OUTFILE 'file_name' SELECT записывает выбранные строки в файл.Файл создается на хосте сервера, поэтому для использования этого синтаксиса у вас должна быть привилегия FILE.имя_файла не может быть существующим файлом, что, помимо прочего, предотвращает уничтожение таких файлов, как /etc/passwd и таблиц базы данных.Начиная с MySQL 5.1.6, системная переменная character_set_filesystem контролирует интерпретацию имени файла.

0 голосов
/ 03 апреля 2017

Из GitHub: https://github.com/OhadR/ohadr.common/blob/master/src/main/java/com/ohadr/common/utils/resultset/ResultSetConverters.java

public static void writeResultSetToWriter(ResultSet resultSet, PrintWriter writer) throws SQLException
{
ResultSetMetaData metadata = resultSet.getMetaData();
int numColumns = metadata.getColumnCount();
int numRows = 0;

while(resultSet.next())             //iterate rows
{
    ++numRows;
    JSONObject obj = new JSONObject();      //extends HashMap
    for (int i = 1; i <= numColumns; ++i)           //iterate columns
    {
        String column_name = metadata.getColumnName(i);
        obj.put(column_name, resultSet.getObject(column_name));
    }
    writer.println(obj.toJSONString());

    if(numRows % 1000 == 0)
        writer.flush();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...