2014-10-26 3 views
1

Я вытаскиваю большое количество json из спокойного сервера. Я использую библиотеку GSON из Google, чтобы пересечь этот json, и он отлично работает. Теперь я хочу сохранить все json-объекты в моем sqlite db, однако я хочу использовать транзакцию, чтобы сразу добавить их все. Это сложно, если у вас нет всех объектов, готовых в одном пакете данных. Поскольку я перемещаю json по одному объекту за раз, я думаю, мне пришлось бы хранить это в структуре данных, такой как arraylist или hashmap, а затем использовать транзакцию базы данных для быстрого вставки. Однако ... Хранение большого количества данных, ака 200 000 объектов json в структуре в памяти может занимать много памяти и, вероятно, тоже закончится. Какой был бы лучший способ получить все эти json-объекты в моем sqlite db и в то же время не использовать много мейнстримов в хранении и вставке других слов таким образом, чтобы это позволяло много перерабатывать.хранение больших данных в android

ответ

0

Я знаю, что это не лучшая реализация обработки большого входа json в Android, но это, безусловно, отлично работает.

Так что мое решение очень простое:

В процессе анализа кода JSON, использовать подготовленных заявлений и транзакции БД для выполнения вставки. Итак, как только объект JSON анализируется, возьмите эту информацию, вставьте ее в db, используя подготовленный оператор и транзакцию db, затем перейдите к следующему объекту.

Я только что вытащил 210 000 строк с 23 полями каждый (это 4,6 миллиона значений) с удаленного сервера через JSON и GSON и в то же время вставив все эти значения в мой SQLite3 db на устройстве, менее чем за 5 минут и без потери памяти. Каждая итерация разбора/вставки использует тот же объем памяти и очищается на следующей итерации.

Итак, есть решение. Очевидно, что это не лучшее решение для коммерческих приложений или таблиц с 1000 000 + записей, но оно отлично подходит для моей ситуации.

+0

Вы должны принять свой собственный ответ, если он самый лучший. Таким образом, читатели futur найдут решение легко. – mithrop

+0

Я через 20 часов. @mithrop – Janpan

1

Если вы хотите добавить большой объем данных в уникальный момент: это займет много памяти. 200 000 больших объектов JSON занимают определенный объем памяти, и вы не сможете его изменить. не.

Вы можете сохранить это поведение, но я думаю, что это не отличное решение, потому что вы создаете огромное потребление памяти на Android-устройстве и на сервере. Будет лучше, если вы получите часть данных по частям и добавьте их следующим образом: но вам нужно иметь контроль над кодом сервера.

Если вы являетесь абсолютно вынуждены сохранять это поведение, возможно, вам следует получать все данные одновременно, проанализировать их на огромном объекте JSON, а затем совершить несколько транзакций. Проверьте, правильно ли выполнялась каждая транзакция, и верните базу данных в хорошем состоянии, если нет. Это очень плохой способ сделать это, ИМХО ... но я не знаю всех ваших ограничений.

Для завершения: избегайте получения большого количества данных всего за один раз. Будет лучше сделать несколько запросов для получения частичного набора данных. Это сделает ваше приложение менее зависимым от сети: если вы потеряете сеть в течение 2 секунд, возможно, только один запрос не удастся. Поэтому вам придется повторить только один запрос и снова получить небольшую часть данных. Только с одним огромным запросом: если вы потеряете сеть, вам придется повторить весь запрос ...

+0

Thx за советом. Я согласен с тем, что делать это не так, но я не могу контролировать некоторые аспекты проекта. Посмотрите на несколько кусков данных вместо одного большого запроса. Выполнение этого с помощью gson, однако, не создает больших транзакций памяти, где, как и одна вставка db одновременно, это нормально, потому что она перерабатывает память, однако это занимает много времени. Я хочу посмотреть, могу ли я держать db открытым во время транзакций. – Janpan

0

Вы когда-нибудь пытались добавить много данных (и я действительно имею в виду много, в моем случае 2600 строк данных) в базу данных Android (SQLite)?

Если это так, вы, возможно, пошли той же дорогой, что и я.

Я пробовал обычный InsertStatement, который был способ замедлить (10 секунд в моем эмуляторе). Затем я попробовал PreparedStatements. Время было лучше, но все же неприемлемо. (6 с). После некоторых разочаровывающих часов написания кода, а затем выбросив его, я наконец нашел хорошее решение.

Android-OS обеспечивает InsertHelper как быстрый способ делать объемные вставки.

Чтобы дать вам представление о производительности (измеряется с эмулятором на дерьмо компьютере, пытаясь вставить 2600 строк данных):

Insert-Statement 
10 seconds 
Prepared-Statements 
6 seconds 
InsertHelper 
320 ms 

Вы можете ускорить вставку еще с временно отключить нити замки. Это увеличит производительность на 30%. Однако важно быть уверенным, что только один поток за время использует базу данных при вставке данных из-за того, что он уже не является потоковым.

public void fillDatabase(HashMap<String, int[]> localData){ 
     //The InsertHelper needs to have the db instance + the name of the table where you want to add the data 
     InsertHelper ih = new InsertHelper(this.db, TABLE_NAME); 
     Iterator<Entry<String, int[]>> it = localData.entrySet().iterator(); 
     final int firstExampleColumn = ih.getColumnIndex("firstExampleColumn"); 
     final int secondExampleColumn = ih.getColumnIndex("secondExampleColumn"); 
     final int thirdExampleColumn = ih.getColumnIndex("thirdExampleColumn"); 
     try{ 
     this.db.setLockingEnabled(false); 
       while(it.hasNext()){ 
         Entry<String, int[]> entry = it.next(); 
         int[] values = entry.getValue(); 
         ih.prepareForInsert(); 
         ih.bind(firstExampleColumn, entry.getKey()); 
         ih.bind(secondExampleColumn, values[0]); 
         ih.bind(thirdExampleColumn, values[1]); 
         ih.execute(); 
       } 
     }catch(Exception e){e.printStackTrace();} 
       finally{ 
         if(ih!=null) 
           ih.close(); 
         this.db.setLockingEnabled(true); 
       } 
     } 
Смежные вопросы