2012-05-27 30 views
1

我目前有一個CSV文件,我解析並試圖將數據插入到android數據庫中。我遇到的問題是插入所有數據的時間過長。這是一個很好的數據量,但我覺得它不應該花20分鐘左右才能完成。Android - 加速在數據庫中插入數據

基本上,我創建了我的數據庫,然後開始解析。在解析每個單獨的CSV行時,我抓取所需的數據並將其插入到數據庫中。總共有大約40000行。

有什麼辦法可以加快這個過程嗎?我試過批量插入,但它從來沒有真正幫助(除非我做錯了)。

代碼如下。

謝謝。

DatabaseHelper(我不得不根據數據的每個CSV行中的量兩個插入命令):

// add zipcode 
    public void add9Zipcode(String zip, String city, String state, String lat, 
      String longi, String decom) { 

     // get db and content values 
     SQLiteDatabase db = this.getWritableDatabase(); 
     ContentValues values = new ContentValues(); 

     db.beginTransaction(); 
     try{ 

      // add the values 
      values.put(KEY_ZIP, zip); 
      values.put(KEY_STATE, state); 
      values.put(KEY_CITY, city); 
      values.put(KEY_LAT, lat); 
      values.put(KEY_LONG, longi); 
      values.put(KEY_DECOM, decom); 

      // execute the statement 
      db.insert(TABLE_NAME, null, values); 

      db.setTransactionSuccessful(); 
     } finally { 
      db.endTransaction(); 
     } 

     db.close(); 

    } 

    public void add12Zipcode(String zip, String city, String state, String lat, 
      String longi, String decom, String tax, String pop, String wages) { 

     // get db and content values 
     SQLiteDatabase db = this.getWritableDatabase(); 
     ContentValues values = new ContentValues(); 

     db.beginTransaction(); 
     try{ 
      // add the values 
      values.put(KEY_ZIP, zip); 
      values.put(KEY_STATE, state); 
      values.put(KEY_CITY, city); 
      values.put(KEY_LAT, lat); 
      values.put(KEY_LONG, longi); 
      values.put(KEY_DECOM, decom); 
      values.put(KEY_TAX, tax); 
      values.put(KEY_POP, pop); 
      values.put(KEY_WAGES, wages); 

      // execute the statement 
      db.insert(TABLE_NAME, null, values); 

      db.setTransactionSuccessful(); 
     } finally{ 
      db.endTransaction(); 
     } 


     db.close(); 
} 

解析文件:

public void parse(ArrayList<String> theArray, DatabaseHandler db) { 

     String[] data = null; 

     // while loop to get split the data into new lines 
     // for loop to split each string in the array list of zipcodes 
     for (int x = 0; x < theArray.size(); x++) { 

      if(x == 10000 || x == 20000 || x == 30000 || x == 40000){ 
       Log.d(TAG, "x is 10k, 20k, 30k, 40k"); 
      } 

      // split string first into an array 
      data = theArray.get(x).split(","); 

      // separate based on the size of the array: 9 or 12 
      if (data.length == 9) { 

       db.add9Zipcode(data[0], data[2], data[3], data[5], data[6], 
         data[8]); 

      } else if (data.length == 12) { 

       db.add12Zipcode(data[0], data[2], data[3], data[5], data[6], 
         data[8], data[9], data[10], data[11]); 

       /* 
       * theZip.zip = data[0]; theZip.city = data[2]; theZip.state = 
       * data[3]; theZip.lat = data[5]; theZip.longi = data[6]; 
       * theZip.decom = data[8]; theZip. = data[9]; theZip.population 
       * = data[10]; theZip.wages = data[11]; 
       */ 

      } 
     } 

回答

3

參考這個答案我做先前:Inserting 1000000 rows in sqlite3 database

總之,請使用InsertHelper並且每個交易做多個插入 - 除非你做了一些不可思議的事,速度的增加應該是顯而易見的。

編輯:
簡而言之:

  1. SQLiteOpenHelper應該是整個應用程序使用的單。
  2. 不要在你的SQLiteDatabase實例上轉過身去呼叫close() - 它被緩存在SQLiteOpenHelper中,每當你關閉時你都強迫幫助者重新打開它。
  3. 批量插入,在調用addZipCode方法之外啓動一個事務,並在完成所有插入後將其標記爲成功 - 然後提交事務。
  4. 使用InsertHelper - 它會將插入操作正確地格式化爲預準備語句,並且很好且可重用。
  5. 請注意同步對數據庫的訪問 - 除非您打算在UI線程上執行所有數據庫工作(不建議這麼做) - 您需要啓用鎖定或防止訪問數據庫以避免併發訪問。
+0

是啊,我想知道如果我確實做了一些不可思議的事情。批量插入代碼已經在我的addZipcode方法中。我做錯什麼了嗎? – Splitusa

+1

你的例子中的兩個'addZipCode'使用每個插入*一個*事務(沒有批處理過的東西) - 它們也爲每次調用關閉數據庫 - 這會強制SQLiteOpenHelper爲每個插入重新打開數據庫文件(do * not *去做)。通常,你不應該一遍又一遍地關閉'SQLiteDatabase'。你的'SQLiteOpenHelper'應該是整個應用程序中使用的單例,而且如果**關閉,很少。 – Jens

+0

感謝您的幫助! – Splitusa