首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQLite -在Android应用程序中加速4,000行插入

SQLite -在Android应用程序中加速4,000行插入
EN

Stack Overflow用户
提问于 2015-04-16 22:49:20
回答 2查看 1.6K关注 0票数 1
代码语言:javascript
复制
public synchronized void updateStop(ArrayList<StopBean> beanList){
    SQLiteDatabase db = getWritableDatabase();
    String query = "DELETE FROM 'stop'";
    db.execSQL(query);
    for(StopBean bean : beanList){
        String atco_code = bean.getAtco_code();
        String name = bean.getName();
        String locality = bean.getLocality();
        String bearing = bean.getBearing();
        String latitude = bean.getLatitude()+"";
        String longitude = bean.getLongitude()+"";

        ContentValues values = new ContentValues();
        values.put("atco_code", atco_code);
        values.put("name", name);
        values.put("locality", locality);
        values.put("bearing", bearing);
        values.put("latitude", latitude);
        values.put("longitude", longitude);
        db.insert("stop", null, values);
    }

    db.close();
}

目前,我们的应用程序通过上面的方法插入了4,000行。这个方法的问题是,实际执行需要10-15秒。显然,对于一个简单的4,000行插入来说,这太长了。

如何更改此方法,使其大大加快这些插入的执行时间?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-16 22:58:08

使用beginTransaction()endTransaction()markTransactionAsSuccessful()将整个事务包装在一个事务中。现在,您正在每个插入执行一个事务,这意味着每插入一个磁盘I/O脉冲,这将是非常慢的。

除此之外:

  • 不要在循环的每次传递中分配一个新的ContentValues
  • 去掉局部变量(例如,atco_code),以防它们没有被优化掉
  • 使用比"“更有效的方法将数字转换为字符串(例如,Double.toString() )
  • 尝试将普通SQL INSERT语句编译为SQLiteStatement compileStatement(),看看这是否比只调用insert()更好。

如果您仍然不高兴,使用Traceview,并确定您的剩余时间是在哪里度过的。

票数 7
EN

Stack Overflow用户

发布于 2015-04-17 00:57:22

sqlite的最新版本 (即Kit Kat、Jelly和Lollipop,根据模拟器)中,您可以使用多插入语句:

代码语言:javascript
复制
INSERT INTO table (col1, col2) VALUES 
  ('row1col1', 'row1col2'), ('row2col1', 'row2col2');

如果您要导入静态受信任的数据,那么在应用程序的文件中包含带有数据的script,然后在启动时运行它。注意:永远不要将SQL值连接到SQL查询中,因为这为数据库注入打开了大门(而且它也不会更快,因为您和sqlite将对数据进行两次解析,并进行不必要的重新序列化)。

如果需要插入动态生成的数据,或者需要支持较早的版本,则应使用准备好的语句预编译SQL查询并使用绑定变量。示例:

代码语言:javascript
复制
db.beginTransaction();
String sql = "INSERT INTO stop(atco_code, name, locality, bearing, latitude, longitude) VALUES (?,?,?,?,?,?)";
SQLiteStatement stmt = db.compileStatement(sql);

for(StopBean stop : stopList){
    stmt.bindString(1, stop.getAtco_code());
    stmt.bindString(2, stop.getName());
    stmt.bindString(3, stop.getLocality();
    stmt.bindString(4, stop.getBearing());
    stmt.bindDouble(5, stop.getLatitude());
    stmt.bindDouble(6, stop.getLongitude());

    stmt.execute();
    stmt.clearBindings();
}

db.setTransactionSuccessful();
db.endTransaction();

在任何情况下,都应该将所有插入都包装在一个事务中。使用单个事务允许数据库缓存快速RAM中的值,并且只在缓存已满或完成时才刷新数据,而不是为每个insert语句将数据刷新到持久存储。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29687283

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档