Как эффективно вставлять объемные данные в базу данных android sqlite с помощью ormlite

Я пытаюсь вставить 100000 записей в базу данных Android sqlite за раз. Я использую следующие два разных метода.

 private void bulkInsertDataBySavePoint(final List<User> users) {
    log.debug("bulkInsertDataBySavePoint()");
    DatabaseConnection conn = null;
    Savepoint savepoint = null;
    try {
        conn = userDao.startThreadConnection();
        savepoint = conn.setSavePoint("bulk_insert");
        for (User user : users) {
            userDao.create(user);
        }
    } catch (SQLException e) {
        log.error("Something went wrong in bulk Insert", e);
    } finally {
        if (conn != null) {
            try {
                conn.commit(savepoint);
                userDao.endThreadConnection(conn);
            } catch (SQLException e) {
                log.error("Something went wrong in bulk Insert", e);
            }
        }
    }
}

А также

   private void bulkInsertDataByCallBatchTasks(final List<User> users) {
    log.debug("bulkInsertDataByCallBatchTasks()");
    try {
        userDao.callBatchTasks(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                for (User user : users) {
                    userDao.create(user);
                }
                return null;
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Оба метода работают нормально. В среднем они занимают 140 секунд и загружают процессор на 60-65%, что, я думаю, ненормально.

Идея в том, что я должен использовать API, который будет предоставлять данные JSON. Мне нужно проанализировать эти данные json, а затем вставить их в базу данных sqlite для автономного использования.

Я ищу эффективный способ решить эту проблему.

Любая мысль?


person rokonoid    schedule 03.07.2013    source источник
comment
Чему вы научились, когда использовали Traceview, чтобы точно определить, на что уходит ваше время?   -  person CommonsWare    schedule 03.07.2013
comment
Я действительно не очень понимаю tracveiw. На этот раз я вызываю System.nanoTime() до и после вызова метода массовой вставки.   -  person rokonoid    schedule 04.07.2013
comment
Я использовал второй метод в одном из своих приложений, и он значительно увеличил время отклика.   -  person voghDev    schedule 12.11.2014
comment
дубликаты (кроме точек сохранения) массовых вставок Ormlite Android   -  person Alexander Malakhov    schedule 05.12.2014
comment
Я должен согласиться с @voghDev, второй уменьшил время загрузки с 16,5 секунд до 1,7 секунд на 1100 элементов. Спасибо вам обоим. :)   -  person JerabekJakub    schedule 25.05.2016


Ответы (3)


Я пытаюсь вставить 100000 записей в базу данных android sqlite за раз... В среднем они занимают 140 секунд и занимают 60-65% ЦП, что, на мой взгляд, не нормально.

К сожалению, у меня нет простого ответа для вас. Возможно, вам придется выполнять такую ​​вставку напрямую, используя необработанный SQL, чтобы добиться более высокой производительности на ограниченном процессоре Android. После того, как вы вставили данные, вы можете обратиться к ORMLite, чтобы запросить или обработать данные быстрее.

person Gray    schedule 16.07.2013
comment
Спасибо @Gray, я думал о том же. - person rokonoid; 22.07.2013
comment
@Gray Мне любопытно, почему метод Dao для массовой вставки, такой как следующий, невозможен: int create(Collection‹T›data) Спасибо за отличный инструмент ORM и за всю помощь, которую вы оказываете! - person Farrukh Najmi; 27.05.2014
comment
Хрм. Хорошая идея @FarrukhNajmi. Я только что добавил его в багажник. Это будет в версии 4.49. - person Gray; 27.05.2014
comment
Потрясающая отзывчивость на комментарии сообщества. Вы и ORMLite крутые! - person Farrukh Najmi; 29.05.2014
comment
Это все еще рекомендуемый способ на Android? - person Alexander Malakhov; 04.12.2014

У меня была такая же проблема, и я нашел разумное решение. Это заняло время вставки от 2 секунд до 150 мс:

final OrmLiteSqliteOpenHelper myDbHelper = ...;
final SQLiteDatabase db = myDbHelper.getWritableDatabase();
db.beginTransaction();
try{
    // do ormlite stuff as usual, no callBatchTasks() needed

    db.setTransactionSuccessful();
}
finally {
    db.endTransaction();
}
person Alexander Malakhov    schedule 05.12.2014
comment
Хотя у меня есть 100% воспроизводимые доказательства того, что этот код помогает, это не так просто и прямолинейно. Подробнее см. здесь - person Alexander Malakhov; 25.08.2015
comment
это мне очень помогло, с 15 с теперь занимает около 2 секунд. Спасибо ! - person sonique; 08.10.2015
comment
Я так и сделал, но это решение гораздо проще реализовать и оно оказалось успешным. - person sonique; 27.11.2015
comment
@sonique хм... Я действительно не понимаю, почему мое решение проще в коде, чем простое callBatchTasks (если производительность в порядке) :) Вы использовали его, как в примерах документа (пример с источником подключения, без) ? - person Alexander Malakhov; 07.12.2015
comment
У меня было много запросов (анализ канала JSON и вставка сотен объектов из 3-4 классов в базу данных sqlite), я думаю, что это решение проще, потому что мне просто нужно было добавить db.beginTransaction(); db.setTransactionSuccessful(); и db.endTransaction(); вокруг моего кода. Где с callBatchTasks, это ссылка на конкретный объект DAO, и с моей точки зрения это немного запутанно. Наконец, да, производительность значительно улучшилась, примерно в 100 раз быстрее. - person sonique; 15.12.2015

Хрм. Хорошая идея @FarrukhNajmi. Я только что добавил его в багажник. Это будет в версии 4.49.

@Gray Он все еще нестабилен? когда мы сможем увидеть это в maven?

И если com.j256.ormlite.dao.ForeignCollection#addAll сделает только один запрос, тоже было бы неплохо.

person Anton Pogonets    schedule 23.10.2014