2011-11-06 50 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文件来存储整个词典并用代码读取它?..更多来研究:) –