在Android设备上批量插入
我想在我的下一次升级时将大约700条logging批量插入到Android数据库中。 什么是最有效的方法来做到这一点? 从各个职位,我知道,如果我使用Insert
语句,我应该包装在一个事务。 还有一个关于使用自己的数据库的post ,但我需要这些数据进入我的应用程序的标准Android数据库。 请注意,这只会在每个设备上执行一次。
一些想法:
-
将一堆SQL语句放在一个文件中,一次读一行,然后执行SQL。
-
把数据放在一个CSV文件,或JSON,或YAML,或XML,或其他。 一次读一行,并执行
db.insert()
。 -
找出如何进行导入,并完成整个文件的单个导入。
-
制作一个包含所有logging的sqlite数据库,将其复制到Android设备上,并以某种方式合并这两个数据库。
-
[编辑]把所有的SQL语句作为一个大string放在res / values中的单个文件中。 然后一次读一行,然后执行SQL。
什么是最好的方法? 还有其他的方式来加载数据? 3和4甚至可能吗?
我不相信有任何可行的方法来完成你的名单上的#3或#4。
在其他解决scheme中,列出了两个数据文件包含直接SQL的数据库,另一个包含非SQL格式的数据。
三者都可以正常工作,但后一种从格式化文件中获取数据并自行构buildSQL的build议似乎是最干净的。 如果在以后的date添加了真正的批量更新function,您的数据文件仍然可用,或者至less可以轻松处理成可用的格式。 而且,创build数据文件更直接,也更不容易出错。 最后,拥有“原始”数据将允许导入其他数据存储格式。
在任何情况下,您都应该(如您所述)将插入组包装到事务中,以避免创build每行事务日记。
通常,每次使用db.insert()
,SQLite都会创build一个事务(并在文件系统中生成日志文件),从而减慢速度。
如果使用db.beginTransaction()
和db.endTransaction()
SQLite将在文件系统上只创build一个日志文件,然后同时提交所有的插入,显着加快速度。
这里有一些伪代码: 批量插入到Android上的SQLite数据库
try { db.beginTransaction(); for each record in the list { do_some_processing(); if (line represent a valid entry) { db.insert(SOME_TABLE, null, SOME_VALUE); } some_other_processing(); } db.setTransactionSuccessful(); } catch (SQLException e) {} finally { db.endTransaction(); }
如果由于意外错误或其他原因想要中止事务,只需简单地使用db.endTransaction()
而不事先将事务设置为成功( db.setTransactionSuccessful()
)。
另一个有用的方法是使用db.inTransaction()
(返回true
或false
)来确定您当前是否处于事务中间。
文档在这里
我发现对于批量插入, DatabaseUtils.InsertHelper类(显然很less使用)比使用SQLiteDatabase.insert
快几倍。
另外两个优化也帮助我的应用程序的性能,但它们可能并不适合所有情况:
- 不要
bind
空值或null
。 - 如果可以确定可以安全地执行此操作,则暂时closures数据库的内部locking也可以提高性能。
我有一个更详细的博客文章 。
那么,我的解决scheme,这有点奇怪,但工作正常…我编译大量的数据,并一次性插入(批量插入?)
我使用db.execSQL(Query)
命令,我用下面的语句构build“查询”…
INSERT INTO yourtable SELECT * FROM ( SELECT 'data1','data2'.... UNION SELECT 'data1','data2'.... UNION SELECT 'data1','data2'.... UNION . . . SELECT 'data1','data2'.... )
唯一的问题是查询的build立可能有点混乱。 我希望它有帮助
下面的这个例子将完美的工作
String sql = "INSERT INTO " + DatabaseHelper.TABLE_PRODUCT_LIST + " VALUES (?,?,?,?,?,?,?,?,?);"; SQLiteDatabase db = this.getWritableDatabase(); SQLiteStatement statement = db.compileStatement(sql); db.beginTransaction(); for(int idx=0; idx < Produc_List.size(); idx++) { statement.clearBindings(); statement.bindLong(1, Produc_List.get(idx).getProduct_id()); statement.bindLong(2, Produc_List.get(idx).getCategory_id()); statement.bindString(3, Produc_List.get(idx).getName()); // statement.bindString(4, Produc_List.get(idx).getBrand()); statement.bindString(5, Produc_List.get(idx).getPrice()); //statement.bindString(6, Produc_List.get(idx).getDiscPrice()); statement.bindString(7, Produc_List.get(idx).getImage()); statement.bindLong(8, Produc_List.get(idx).getLanguage_id()); statement.bindLong(9, Produc_List.get(idx).getPl_rank()); statement.execute(); } db.setTransactionSuccessful(); db.endTransaction();