性能 SQLite 问题 - 代码更改可以加快速度吗?

发布于 2024-12-13 17:05:54 字数 622 浏览 0 评论 0原文

我使用以下代码向数据库添加行:

    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;

目前,我调用此 insert() 3.455 次,以将所有单词添加到数据库,使用: insert("Fruits", "Banana");这需要永远。

我怎样才能改变这个代码以使其工作得更快?我正在考虑 foreach,但不知道如何实现..谢谢!

/编辑; @hovanessyan 提供的解决方案有效并且可以完成这项工作。并且..请注意,如果您有很多必须放入的行,您可能会遇到该方法超出最大字节限制错误。在这种情况下,请查看其他解决方案,该解决方案建议将数据库打包在实际的 .APK 文件中。

I use the following code to add rows to my database :

    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;

Currently, I'm invoking this insert() 3.455 times, to add all words to the database, using : insert("Fruits", "Banana"); It takes forever.

How can I change this code to work faster? I'm thinking in the line of foreach, but don't know how to implement.. Thanks!

/Edit; The solution provided by @hovanessyan works and will do the job. AND.. note that if you have a lot of lines that have to be put in, you might be confronted with the method exceeds max byte limit error. In that case, review the other solution, that suggests packing the database in the actual .APK file.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

安静 2024-12-20 17:05:54

您可以将这些插入打包到事务中。

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
 }

You can wrap-up those inserts into transaction.

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
 }
做个ˇ局外人 2024-12-20 17:05:54

您可以使用批量插入:

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

You can use 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);
暮色兮凉城 2024-12-20 17:05:54

使用 hovanessyan 和 Damian 的技巧(提醒我在达到 15 级后立即对你进行 +1 ;),我想出了以下解决方案:

  1. 对于相对较小的数据库 (<1,5Mb),

我使用 SQLite 创建了数据库数据库浏览器,并将其放入我的资产文件夹中。

然后,以下代码将数据库复制到设备(如果该设备尚不存在):

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

public void copyDB() throws IOException{
最终字符串 DB_DESTINATION = "/data/data/happyworx.nl.Flitswoorden/databases/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 设置为“false”并等待用户返回到主要活动。 (从而调用 onstart 并复制原始数据库)。

我尝试从preferences.java 调用Activity.copyDB()。它更简洁,因为它不需要用户返回主活动来重建数据库。但是,我收到有关无法调用对非静态方法的静态引用的错误。我不太明白,但会研究一下。

Using the tips of both hovanessyan and Damian (remind me to rep+1 you as soon as I reach 15 ;), I came up with the following solution:

  1. For relatively small databases (<1,5Mb)

I created the database using SQLite Database Browser, and put it in my Assets folder.

Then, the following code copies the database to the device, if it's not already there:

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

public void copyDB() throws IOException{
final String DB_DESTINATION = "/data/data/happyworx.nl.Flitswoorden/databases/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();
    }}

In my app, a portion of the database is User-customizable.

I call the code above in onStart() with :

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

So, when the user presses "reset database to standard" (in preferences screen), I just set the Boolean initialiseDatabase to "false" and wait for the user to go back to the main activity. (thus calling onstart and copying the original database).

I tried to call the Activity.copyDB() from the preferences.java. It's neater, because it doesn't require the user to go back to the main activity to rebuild the database. However, I get an error about not being able to call static references to non-static methods. I don't understand that, but will look into it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文