【问题标题】:Android Sqlite PerformanceAndroid Sqlite 性能
【发布时间】:2015-01-28 09:00:36
【问题描述】:

我一直在做一些实验来测量 android 上的 sqlite 性能。我对结果有点失望。我所做的是向表中插入 10.000 个查询,花了 130-140 秒 但在这些条件下

1.三星galaxy s3处于省电模式

2. 插入的数据(或类)有 3 个字符串和 1 个浮点数(对于 sqlite 是实数)

3. 正在异步任务中完成插入事件。

4. 在 asynctask 中,我正在显示一个进度对话框,其中包含传递的计时器文本(System.currentTimeMillis - seconds etc blala)

class AddStudentsTask extends AsyncTask<Void,Integer,Void>
{
    ProgressDialog prgDialog;
    int max = 10000;
    Student s;
    long seconds = System.currentTimeMillis();


    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        prgDialog = new ProgressDialog(MainActivity.this);
        prgDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        prgDialog.setMessage(seconds+"");
        prgDialog.setMax(max);
        prgDialog.setCancelable(false);
        prgDialog.show();

    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate();
        prgDialog.setProgress(values[0]);
        sList.add(s);
        String s = (System.currentTimeMillis()-seconds)/100+"";
        if(s.length()>2)
            s = s.substring(0,s.length()-1) + "." + s.charAt(s.length()-1);
        else if(s.length() == 2)
            s = s.charAt(0) + "." + s.charAt(1);
        prgDialog.setMessage(s + " seconds passed.");

    }

    @Override
    protected Void doInBackground(Void... voids) {

        for(int a = 0;a< max; a++ )
        {
            Random r = new Random();
            s = new Student();

            s.setGpa(r.nextFloat()*4);
            s.setLastName("asdasd");
            s.setFirstName("Oh My God");
            s.setAddress("1sadasd");
            s.setId(sda.insert(s));
            publishProgress(a);
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        prgDialog.dismiss();
        sa.notifyDataSetChanged();
    }
}

5. 我在 helperdb 类中使用 contentValues 和 insertOrThrow 方法。 这是旧的慢代码

public long insert(Student s)
{
    SQLiteDatabase db = sh.getWritableDatabase();
    ContentValues cv = new ContentValues();
    cv.put(StudentHelper.FIRSTNAME,s.getFirstName());
    cv.put(StudentHelper.LASTNAME,s.getLastName());
    cv.put(StudentHelper.ADDRESS,s.getAddress());
    cv.put(StudentHelper.GPA,s.getGpa());
    s.setId(db.insertOrThrow(StudentHelper.TABLE_NAME, null, cv));
    return s.getId();
}

6.这个任务在activity的onCreate方法中完成。

那么我在这里做错了什么或期望过高呢?这些结果是好还是坏?

我可以做些什么来改进我的代码?

编辑

所以我把我的插入代码改成了这个,它减少到 4.5 秒!!!

public ArrayList<Long> insertMany(ArrayList<Student> stus)
{
    ArrayList<Long> ids = new ArrayList();
    String sql = "INSERT INTO "+StudentHelper.TABLE_NAME+"" +
            "("+StudentHelper.FIRSTNAME+","+StudentHelper.LASTNAME+"," +
            " "+StudentHelper.GPA+") values(?,?,?)";
    SQLiteDatabase db = sh.getWritableDatabase();
    db.beginTransaction();

    for(Student s:stus) {
        SQLiteStatement stmt = db.compileStatement(sql);

        stmt.bindString(1, s.getFirstName());
        stmt.bindString(2, s.getLastName());
        stmt.bindDouble(3, s.getGpa());

        s.setId(stmt.executeInsert());
        ids.add(s.getId());
        stmt.clearBindings();
    }

    db.setTransactionSuccessful();
    db.endTransaction();

    return ids;
}

【问题讨论】:

  • 我看不到 endTransactionsetTransactionSuccessful 如果您只是在您的 beginTransaction 方法中添加了 insert ,那么您错过了整个重点。
  • @M-WaJeEh 你是对的。我编辑了我的帖子。感谢您的建设性批评!
  • 不,还是错了。你必须先做beginTransaction,然后是 10.000 次插入,然后是 setTransactionSuccessful,然后是 endTransaction。修改您的 AddStudentsTask 以使其正常工作。
  • 我明白了,是的,您是说我要重新打开 10k 次以进行插入。我明白了,谢谢=)。我为未来的问题爱好者编辑了帖子,让他们对使用有所了解。
  • 是的,这个很完美。

标签: android android-asynctask android-sqlite


【解决方案1】:

使用SQLite transaction 加快速度

使用 BEGIN TRANSACTIONEND TRANSACTION 进行 SQLite 优化

默认情况下,SQLite 运行时将每个 SQL 语句包含在一个新的事务块中。所以当你执行一个基本的数据库操作比如INSERT时,一个事务块会被创建并包裹在它周围。

仅当您的例程仅对数据集执行一个 DB 操作时,才建议让 SQLite 运行时为您管理事务。但是,如果您正在执行大量 DB 操作(例如,在 for 循环中的 INSERT),这将变得非常昂贵,因为它需要为每个语句重新打开、写入和关闭日志文件。 你可以参考

  1. Android SQLite database: slow insertion

  2. http://www.androidcode.ninja/android-sqlite-transaction-tutorial/

  3. http://www.techrepublic.com/blog/software-engineer/turbocharge-your-sqlite-inserts-on-android/

  4. http://www.android-app-market.com/sqlite-optimization-in-android-programming-sqlite-optimization-in-android-apps.html

【讨论】:

  • 上面只是一个链接,没有别的,所以你会提供一些解释
  • 感谢您的回答。它加快了 20 倍大声笑。耗时 7.5 秒
  • 我为未来的问题解决者编辑了我的帖子,以便他们可以更改他们的代码。
【解决方案2】:

您可以像这样在 Android 中使用 SQL 事务。最好将多行大批量插入数据库,然后为每个插入的行进行单次提交(写入非常慢的 SQLlite 数据文件)。

public void insert(List<Student> students)
{
    SQLiteDatabase db = sh.getWritableDatabase();
    ContentValues cv = new ContentValues();

    db.beginTransaction();

    try {
        for (Student s : students) {
            cv.put(StudentHelper.FIRSTNAME,s.getFirstName());
            cv.put(StudentHelper.LASTNAME,s.getLastName());
            cv.put(StudentHelper.ADDRESS,s.getAddress());
            cv.put(StudentHelper.GPA,s.getGpa());

            db.insertOrThrow(StudentHelper.TABLE_NAME, null, cv)
        }
        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
    }
}

【讨论】:

  • 非常感谢您提供此解决方案。这确实提高了性能。
【解决方案3】:

嗯,你有这么多的记录,每条记录都调用getWritableDatabase() 然后插入它,这对性能不利。

您需要使用事务。看看这个问题Android SQLite database: slow insertion。基本上你需要打电话给beginTransaction(),做你的插入,然后打电话给setTransactionSuccessful(),前面是endTransaction()。您会惊讶地看到您将获得多少性能提升。

【讨论】:

    猜你喜欢
    • 2013-03-03
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 2012-08-26
    • 2013-04-12
    • 2011-10-27
    • 1970-01-01
    • 2015-02-23
    相关资源
    最近更新 更多