在android中将大量数据插入sqlite

时间:2012-05-16 11:25:08

标签: android sqlite insert

目前,我必须一次向我的机器人插入超过10亿个数据。但是,内存不足的问题会导致程序崩溃。 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个工作吗?

2 个答案:

答案 0 :(得分:3)

一些事情:

  1. See my answer here了解批量INSERT时的一般提示。
  2. 不需要为INSERT语句设置临时容器(在本例中为ArrayList&lt;&gt;)。只需在try ... finally中使用beginTransaction()endTransaction()
  3. 通过SQLiteStatement使用预编译的语句来构建每个INSERT语句,如示例所示。这是不必要的颠簸。
  4. 快速而肮脏的例子:

    // 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;
    }
    

答案 1 :(得分:0)

您可以简单地开始在创建查询字符串的同一循环中插入记录,而不是创建包含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由于持有如此多记录而导致的原因。

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