Страницы

Поиск по вопросам

вторник, 25 февраля 2020 г.

Android - как ещё можно ускорить вставку в базу SQLite?

#android #java #sqlite


Здравствуйте! По совету из прошлого вопроса я не стал записывать нулевые ячейки в
базу, теперь объём записываемых данных уменьшился с 25 165 824 до 6 881 280. Вопрос:
можно ли ещё как-нибудь ускорить сохранение (сейчас оно занимает 140 секунд, хотелось
бы сократить это время хотя бы до минуты) этих данных в базу?
Вот мой код сохранения:

    void save()
    {
        final SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(path, null);
        String sql_w_table = 
            "CREATE TABLE w_data (" +
            "a LONG," +
            "b LONG," +
            "type LONG" +
            ");";
        database.execSQL(sql_w_table);

        String query = "INSERT INTO w_data VALUES (?,?,?);";
        SQLiteStatement st = database.compileStatement(query);

        database.beginTransaction();

        for (int i = 0; i <= 32767; i++)
        {
            for (int n=0; n <= 255; n++)
            {
                int b = map[i][n];

                if (b != 0)
                {
                    st.bindLong(1, i);
                    st.bindLong(2, n);
                    st.bindLong(3, b);
                    st.executeInsert();
                    st.clearBindings();
                }
            }
        }

        database.setTransactionSuccessful();
        database.endTransaction();
        database.close();           
    }
    


Ответы

Ответ 1



Предлагаю самый наивный способ - не сохранять "поячеечно", а "построчно". Попробую на коленке переписать (!!). void save() { final SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(path, null); String sql_w_table = "CREATE TABLE w_data (" + "a LONG," + "type TEXT" + ");"; database.execSQL(sql_w_table); String query = "INSERT INTO w_data VALUES (?,?);"; SQLiteStatement st = database.compileStatement(query); database.beginTransaction(); for (int i = 0; i <= 32767; i++) { String s = ''; for (int n=0; n <= 255; n++) { s += map[i][n] + " "; } st.bindLong(1, i); st.bindLong(2, s); st.executeInsert(); st.clearBindings(); } database.setTransactionSuccessful(); database.endTransaction(); database.close(); } суть - в базу сохраняем сразу по строке. Когда нужно будет распаковывать, то используем обычный метод split у строки. Можно пойти дальше и использовать blob и сохранять строку в один подход. Андроидовская обвязка для blob умеет сохранять массив byte. Класс java.nio.IntBuffer и java.nio.ByteBuffer позволяют завернуть массив int в массив byte. Вот пример как сохраняют картинку в базу. Но я верю, что сохранение в файл будет как минимум не медленнее (если только не сохранять поэлементно).

Ответ 2



Одного не понимаю, зачем здесь нужны транзакции в локальной БД куда юзер/аппа имеет монопольный доступ? Ну я бы еще понял, если автор где-то при ошибке вставки откатывал бы транзакции и проч. - но этого ведь нет. Раз так, то напрашивается рецепт: для ускорения вставок я бы рекомендовал установить наинизший возможный уровень изоляции транзакций: PRAGMA read_uncommitted = 1; И убрал бы словеса beginTransaction/endTransaction и проч. ненужную в данном контексте муть Еще бы поигрался с местом хранения временных файлов: PRAGMA temp_store = 0 | DEFAULT | 1 | FILE | 2 | MEMORY;

Ответ 3



Судя по коду, bulk insert вам поможет.

Ответ 4



Попробуйте установить другой вариант синхронизации: PRAGMA synchronous = 0 | OFF | 1 | NORMAL | 2 | FULL; Но тут надо понимать что если вырубание питания, или ещё какой непредвиденный косяк у Вас может "умереть" база. Хотя PRAGMA synchronous = 0 скорость увеличится раз в 10сять. И попробуйте ещё закидывать не по одному инсерту а по "пачке".

Комментариев нет:

Отправить комментарий