2012-05-16 47 views
3

中插入大量數據到sqlite中,我必須一次向我的android插入超過10億的數據。但是,內存不足會導致程序崩潰。 sqlite插入測試非常簡單。只需使用for循環來生成sql insert命令,並通過「begin」和「commit」來wrqpped。目前在android

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個工作嗎?

+0

很好的問題+1。 – Herry

+0

請訪問我的[回覆](http://stackoverflow.com/a/9141116/996493),這可能會給你一些想法 – Lucifer

+0

Logcat說什麼?在這裏展示。 – Herry

回答

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(我認爲)是內存不足的原因是由於控股如此如此多的記錄。

並確保您使用外部存儲器來承載您的數據庫文件,否則不是所有的手機都有更大的內部存儲器。

3

有幾件事情:

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