2011-11-06 31 views
0

我用下面的代碼行添加到我的數據庫:性能SQLite問題 - Codechange可以加快速度嗎?

public void insert(String kern, String woord) { 
     SQLiteDatabase db = getWritableDatabase(); 

     ContentValues values = new ContentValues(); 
     values.put(KERN, kern); 
     values.put(WOORD, woord); 

     db.insertOrThrow(TABLE_NAME, null, values); 
     return; 

目前,我調用該插件()3.455倍,對所有單詞添加到數據庫,使用:insert("Fruits", "Banana");它需要永遠。

如何更改此代碼以更快速地工作?我想在foreach的行,但不知道如何實現..謝謝!

/編輯; @ hovanessyan提供的解決方案可以完成這項工作。並注意,如果你有很多行必須放入,你可能會遇到超過最大字節限制錯誤的方法。在這種情況下,請查看其他解決方案,該解決方案建議將數據庫打包到實際的.APK文件中。

+0

爲什麼你需要回報;在一個無效的方法? – hovanessyan

回答

0

同時使用hovanessyan和達米安的提示(提醒我要代表+ 1你,只要我達到1500;),我想出了以下溶液:

  1. 對於相對小的數據庫(< 1,5MB)

我使用SQLite數據庫瀏覽器創建了數據庫,並將其放入我的資源文件夾中。

然後,將下面的代碼複製數據庫的設備,如果它尚未有:

boolean initialiseDatabase = (new File(DB_DESTINATION)).exists(); 

公共無效COPYDB()拋出IOException異常{ 最終字符串DB_DESTINATION =「/數據/數據/ happyworx。 nl.Flitswoorden /數據庫/ WoordData.db「;

// Check if the database exists before copying 


    Log.d("Database exist", "" + initialiseDatabase); 
    Log.d("Base Context", "" + getBaseContext()); 

    if (initialiseDatabase == false) { 

     // Open the .db file in your assets directory 
     InputStream is = getBaseContext().getAssets().open("WoordData.db"); 


     // Copy the database into the destination 
     OutputStream os = new FileOutputStream(DB_DESTINATION); 
     byte[] buffer = new byte[1024]; 
     int length; 
     while ((length = is.read(buffer)) > 0){ 
      os.write(buffer, 0, length); 
     } 
     os.flush(); 

     os.close(); 
     is.close(); 
    }} 

在我的應用程序中,數據庫的一部分是用戶可自定義的。

我叫上面的代碼中調用onStart()與:

 try { 
     copyDB(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

所以,當用戶按下「復位數據庫標準」(在首屏),我只設置布爾initialiseDatabase「假」並等待用戶回到主要活動。 (因此調用啓動並複製原始數據庫)。

我試圖從preferences.java調用Activity.copyDB()。它很整潔,因爲它不需要用戶返回主要活動來重建數據庫。但是,我得到一個關於無法調用靜態引用到非靜態方法的錯誤。我不明白,但會研究它。

4

您可以將這些插入事件包裝到事務中。

db.beginTransaction(); 
try { 
    // do all the inserts here 

    //method call here, that does 1 insert; For example 
    addOneEntry(kern,woord); 
    ... 
    db.setTransactionSuccessful(); 
} catch (SQLException e) { 
     //catch exceptions 
} finally { 
    db.endTransaction(); 
} 


private void addOneEntry(String kern, String woord) { 
    //prepare ContentValues 
    //do Insert 
} 
+0

...和它背後的理論是,如果你不這樣做,那麼SQLite將在每一次插入(自動提交行爲)上提交,這會降低你的速度。 – 2011-11-06 14:58:44

+0

謝謝!所以..這意味着,在你的例子中,我會插入'db.insertOrThrow(TABLE_NAME,null,values);'?那麼,如何在不使用ContentValues的情況下獲得「Fruits」,「Bananas」等?即什麼應該是語法而不是「價值」? –

+0

您實際上仍然使用ContentValues。 – hovanessyan

0

您可以使用bulkInsert:

ContentValues[] cvArr = new ContentValues[rows.size()]; 
    int i = 0; 
    for (MyObject row : rows) { 
    ContentValues values = new ContentValues(); 
    values.put(KERN, myObject.getKern()); 
    values.put(WOORD, myObject.getWoord);  
    cvArr[i++] = values; 
    }// end for 
    resolver.bulkInsert(Tasks.CONTENT_URI, cvArr); 
+0

在這個例子中什麼是MyObject?它是如何格式化的?第一個答案適用於我,但面臨着超過65535字節的限制...... :(。 –

+1

MyObject只是一個類,它擁有你想要的值存儲例如類MyObject {private String kern; private String woord; public String getKern(){return kern;} public String getWoord(){return woord;}} – Damian

+0

啊。好。但是這並沒有幫助超過65535字節的限制問題。更多我來思考一下,我可能想要使用Values文件來存儲整個詞典並用代碼讀取它?..更多來研究:) –