【问题标题】:insert a lot of data into sqlite in android在android中将大量数据插入sqlite
【发布时间】:2012-05-16 11:25:07
【问题描述】:

目前,我必须一次向我的 android 中插入超过 100 亿条数据。但是,内存不足的问题会使程序崩溃。 sqlite 插入测试非常简单。只需使用 for 循环生成 sql insert 命令并由“begin”和“commit”进行 wrqpped。

    private ArrayList<String> sqlInsertCmd = new ArrayList<String>();
    int QUERIES_TIMES = 10000000;
    private void CreateInsertQueries()
    {
        Random localRandom = new Random();
        int i = 0;
        while (i < QUERIES_TIMES)
        {
            int j = localRandom.nextInt(100000);
            sqlInsertCmd.add("insert into " + TABLE + " (a,b,c) values (" + i + "," + 
            j + ",'" + String.valueOf(j) + "')");
            ++i;
        }
    }

    Then..

    mDB.beginTransaction();
    for (int i=0; i<this.QUERIES_TIMES; i++)
    {
        mDB.execSQL(sqlInsertCmd.get(i));
    }
    mDB.setTransactionSuccessful();
    mDB.endTransaction();

有什么办法可以避免内存不足?

谢谢大家,但上面的代码只是一个简单的例子。在我的程序中,它更复杂。我必须在容器中存储一些东西(例如 hashMap)并动态构建 sql 语句。我可以创建 10 个服务,每个服务处理 1/10 个工作吗?

【问题讨论】:

  • 请访问我的answer,这可能会给你一些想法
  • 你的 Logcat 说什么?在这里显示。
  • 最好的选择可能是去路西法答案。
  • 如果数据太大,则将数据作为文本文件存储在外部存储器中,并将该文本文件的路径存储在数据库中。它会比在数据库中存储大量数据慢一点,但更好

标签: android sqlite insert


【解决方案1】:

几件事:

  1. See my answer here 获取批量插入时的一般提示。
  2. 不需要为您的 INSERT 语句提供临时容器(在本例中为 ArrayList)。只需在尝试中使用beginTransaction()endTransaction()...最后。
  3. 通过SQLiteStatement 使用预编译语句,而不是像您的示例中那样构建每个 INSERT 语句。这是不必要的折腾。

快速而肮脏的例子:

// note: untested code used for illustration!
private boolean bulkInsertData(SQLiteDatabase db, final String tableName) {
    final int NUM_ROWS = 10000000;

    Random random = new Random();

    try {
        SQLiteStatement insStmt = insStmt = db.compileStatement("INSERT INTO " + tableName + " (a, b, c) VALUES (?, ?, ?);");
        db.beginTransaction();
        try {
            for(int i = 0; i < NUM_ROWS; i++) {
                insStmt.bindLong(1, i);
                insStmt.bindLong(2, random.nextInt(100000));
                insStmt.bindString(3, String.valueOf(i));
                insStmt.executeInsert();    //  should really check value here!
            }
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();    
        }
    } catch(SQLException se) {
        return false;
    }

    return true;
}

【讨论】:

    【解决方案2】:

    您可以简单地在创建查询字符串的同一循环中开始插入记录,而不是创建一个包含 10000000 个 sql 查询的 ArrayList(这可能是 OutOfMemory 的潜在原因)。例如:

    private void CreateInsertQueries(SQLiteDatabase mDB)
    {
        Random localRandom = new Random();
        int i = 0;
        String query;
    
        try{
            mDB.beginTransaction();
    
            while (i < QUERIES_TIMES)
            {
                int j = localRandom.nextInt(100000);
                query = "insert into " + TABLE + " (a,b,c) values (" + i + "," + 
                j + ",'" + String.valueOf(j) + "')";
                ++i;
    
                mDB.execSQL(query);
            }
    
            mDB.setTransactionSuccessful();
        }
        catch (SQLException e) { e.printStackTrace(); }
        finally{ mDB.endTransaction(); }
    }
    

    这样做将帮助您跳过 ArrayList,这(我认为)是 OutOfMemory 的原因,因为它持有如此多的记录。

    并确保您确实使用外部内存来托管您的数据库文件,否则并非所有手机都有更大的内部内存。

    【讨论】:

      猜你喜欢
      • 2011-09-21
      • 1970-01-01
      • 1970-01-01
      • 2013-06-03
      • 2018-07-15
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多