You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android SQLite插入速度慢于iOS,如何优化大数量插入耗时?

缩短Android SQLite批量插入耗时的优化方案

针对你在三星M30s上插入30万条数据耗时11秒,以及实际项目中30秒的问题,结合SQLite的特性,我整理了几个关键优化方向,能帮你大幅提升插入速度:

  • 使用批量INSERT语句减少SQL执行次数
    你当前的代码每条数据都执行一次execute(),这会产生大量SQL解析和磁盘IO操作。可以把多条数据合并到一个INSERT语句中,比如每1000条执行一次批量插入,能显著减少SQLite的调用次数。示例代码如下:

    MyDb myDb = new MyDb(this);
    SQLiteDatabase db = myDb.getWritableDatabase();
    db.beginTransaction();
    try {
        int batchSize = 1000;
        StringBuilder sb = new StringBuilder("INSERT INTO fieldpoint (pointId, definitionId, modified, value) VALUES ");
        for (int i = 0; i < count; i++) {
            sb.append(String.format("(%d, %d, %d, '%s'),", i, i+10, 0, "myDbTest"));
            // 达到批量阈值就执行一次插入
            if ((i + 1) % batchSize == 0) {
                sb.setLength(sb.length() - 1); // 移除最后一个多余的逗号
                db.execSQL(sb.toString());
                // 重置StringBuilder准备下一批
                sb.setLength(0);
                sb.append("INSERT INTO fieldpoint (pointId, definitionId, modified, value) VALUES ");
            }
        }
        // 处理剩余不足批量大小的数据
        if (sb.length() > "INSERT INTO fieldpoint (pointId, definitionId, modified, value) VALUES ".length()) {
            sb.setLength(sb.length() - 1);
            db.execSQL(sb.toString());
        }
        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
        db.close();
        myDb.close();
    }
    

    注意:如果数据包含特殊字符(比如单引号),要做好转义,或者结合参数绑定避免SQL注入风险。

  • 调整SQLite同步模式降低磁盘IO开销
    默认的synchronous=FULL会强制每次写入都同步到磁盘,这是为了数据安全,但批量插入时可以临时降低同步级别:

    db.execSQL("PRAGMA synchronous = NORMAL;");
    

    插入完成后再改回FULL保障数据安全:

    db.execSQL("PRAGMA synchronous = FULL;");
    

    若对临时数据丢失风险接受度高,甚至可以设为OFF,速度提升会更明显。

  • 临时禁用外键约束和触发器
    如果你的表有外键约束或触发器,每次插入都会触发额外的检查和操作,拖慢速度。可以在事务开始前临时禁用:

    db.execSQL("PRAGMA foreign_keys = OFF;");
    

    插入完成后再重新开启:

    db.execSQL("PRAGMA foreign_keys = ON;");
    
  • 优化WAL模式的使用
    你当前开启了WAL,但它更适合高并发读场景。单线程批量插入时,关闭WAL可能获得更好性能:

    db.disableWriteAheadLogging();
    

    若需要保留WAL,也可以用beginTransactionNonExclusive()替代beginTransaction(),避免独占锁,提升少量效率。

  • 复用预编译语句时优化执行逻辑
    如果你坚持用预编译语句,可将execute()替换为executeInsert()——它是专门为插入操作设计的,能带来微小的性能提升。同时确保循环内只做必要操作,避免额外的对象创建或计算。

内容的提问来源于stack exchange,提问作者SAM8

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 22:23:11