2014-10-26 85 views
1

我从一个宁静的服务器上拖出大量的json。我使用谷歌的GSON库来遍历这个json,它效果很好。现在我想将所有json对象保存在我的sqlite数据库中,但是我想使用事务来一次添加所有这些对象。如果你没有在一个datastructe中准备好所有的对象,这很困难。由于我一次遍历一个json对象,所以我想我必须将其存储在数据结构中,例如arraylist或hashmap,然后使用数据库事务来快速执行插入操作。然而......将大量数据(又称为20000个json对象)存储到内存中的结构中可能占用大量内存,并且可能会用完。将所有json对象放入我的sqlite数据库中的最佳方式是什么?同时,不要使用其他语言中的许多menory来存储和插入,以便进行大量的回收。在android中存储大量数据

回答

0

我知道这不是在Android中处理大型json输入的最佳实现,但它确实很好。

所以我的解决方案很简单:

在解析JSON代码,利用预处理语句和数据库事务执行插入。 因此,简而言之,只要解析JSON对象,就可以使用准备好的语句和db事务将该信息插入到数据库中,然后转到下一个对象。

我刚刚从远程服务器通过JSON和GSON抽取了210,000行,每个23个字段(即460万个值),同时将所有这些值插入到设备上的SQLite3数据库中,少于5个分钟而不浪费任何内存。每次解析/插入迭代使用相同数量的内存,并在下一次迭代时进行清理。

所以是的,有解决方案。显然,这不是商业应用程序或具有1000 000条记录的表格的最佳解决方案,但对我的情况非常有用。

+0

如果它是最好的,你应该接受你自己的答案。这样,未来的读者将很容易找到解决方案。 – mithrop 2014-10-27 08:59:24

+0

我会在20小时内。 @mithrop – Janpan 2014-10-27 19:35:43

1

如果你想在一个独特的时刻添加大量的数据:无论如何它会占用大量的内存。 200 000个大的JSON对象需要一定的内存,并且您将而不是能够更改它。

您可以保持这种行为,但我认为这不是一个很好的解决方案,因为您在Android设备和服务器上都创建了巨大的内存消耗。如果您逐个接收数据并以这种方式添加数据会更好:但您需要控制服务器代码。

如果你是绝对被迫保持这种行为,也许你应该在同一时间接收所有的数据,解析它们在一个巨大的JSON对象,然后进行多个事务。检查每个事务是否正确执行,如果没有,则将数据库恢复到良好状态。这是一个非常糟糕的方式,恕我直言...但我不知道你所有的限制。

完成:避免一次只接收大量数据。多次请求获取部分数据集会更好。它会使您的应用程序减少网络依赖性:如果您将网络断开2秒,则可能只有一个请求会失败。所以你将不得不重试只有一个请求,并再次收到一小部分数据。只有一个巨大的请求:如果你松动了网络,你将不得不重试整个请求...

+0

Thx的意见。我同意这样做并不理想,但我对项目的某些方面几乎没有控制权。将考虑多个数据块而不是一个大的请求。然而,使用gson做它并不会创建任何大内存事务,因为一次执行一个数据库插入也没有问题,因为它可以回收内存,但需要很长时间。我想看看我是否可以在交易时保持数据库的开放。 – Janpan 2014-10-26 17:19:39

0

你有没有试过在Android内部数据库(SQLite)中添加大量数据(我的意思是很多,在我的情况下是2600行数据)?

如果是这样,你可以和我一样走上同样的道路。

我试过一个正常的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); 
       } 
     }