代码之家  ›  专栏  ›  技术社区  ›  Samuh

针对Android应用程序的SQLite优化

  •  10
  • Samuh  · 技术社区  · 14 年前

    1. 在where子句中使用位置参数(原因:以便sqlite使用相同的执行计划)
    2. 索引:除了在“主键”和“唯一键”列上默认创建的索引外,我没有创建任何显式索引。(原因:索引将提高寻道时间)

    我在偏执中提到过我的假设,如果我错了,请纠正我。

    问题:

    1. SQLite3中是否允许嵌套事务?它们如何影响性能? 问题是我有一个在循环中运行更新的函数,所以,我将循环封装在一个事务块中。有时这个函数是从其他函数中的另一个循环调用的。调用函数还将循环封装在事务块中。这样的事务嵌套如何影响性能?

    4 回复  |  直到 14 年前
        1
  •  12
  •   Robie Basak    14 年前
    1. 确定需要优化的查询。获取典型数据库的副本并使用REPL to time查询。当你优化时,用这个来衡量任何收益。

    2. 使用 ANALYZE

    3. 为了 SELECT s和 UPDATE EXPLAIN QUERY PLAN 在查询中查看将使用哪个索引或查询是否需要全表扫描。对于大型表,完整表扫描不好,您可能需要索引。对于任何给定的查询,将只使用一个索引。如果有多个谓词,那么将使用的索引将是预期减少结果集最多的索引(基于 分析 ). 可以有包含多个列的索引(以帮助查询多个谓词)。如果索引包含多个列,则仅当谓词从左到右与索引匹配且没有间隙时,这些索引才可用(但末尾未使用的列可以使用)。如果使用顺序谓词( < <= , > WHERE 谓词和 ORDER BY 两者都需要一个索引,而SQLite只能使用一个索引,因此这可能会影响性能。索引越多,速度越慢 INSERT 是的,所以你必须为你的处境做出最好的权衡。

    4. 如果您有更复杂的查询,无法使用可能创建的任何索引,则可以取消模式规范化,以更简单的方式构造数据,并可以使用索引来回答查询。

    5. 如果你做了大量的 s、 尝试删除索引并在最后重新创建它们。你需要对它进行基准测试。

    6. 数据库 does support nested transactions

    7. 你可以 gain lots of speed by compromising on data integrity . 如果您可以自己从数据库损坏中恢复,那么这可能对您有用。可能只有在执行可以手动恢复的密集操作时才能执行此操作。

    我不确定你能从Android应用中得到多少。有一个 more detailed guide 用于在SQLite文档中优化SQLite。

        2
  •  9
  •   Robert Tupelo-Schneck    13 年前

    EXPLAIN QUERY PLAN 从正在运行的Android应用程序生成Android logcat。我从一个 SQLiteOpenHelper dbHelper SQLiteQueryBuilder qb .

    String sql = qb.buildQuery(projection,selection,selectionArgs,groupBy,having,sortOrder,limit);
    android.util.Log.d("EXPLAIN",sql + "; " + java.util.Arrays.toString(selectionArgs));
    Cursor c = dbHelper.getReadableDatabase().rawQuery("EXPLAIN QUERY PLAN " + sql,selectionArgs);
    if(c.moveToFirst()) {
        do {
            StringBuilder sb = new StringBuilder();
            for(int i = 0; i < c.getColumnCount(); i++) {
                sb.append(c.getColumnName(i)).append(":").append(c.getString(i)).append(", ");
            }
            android.util.Log.d("EXPLAIN",sb.toString());
        } while(c.moveToNext());
    }
    c.close();
    

    我把这个放进了我的 ContentProvider.query() 现在我可以确切地看到所有查询是如何执行的。(在我看来,问题是 查询太多

        3
  •  1
  •   srinathhs    14 年前

    我想补充一下:

    1. 在某些情况下,使用rawQuery()而不是使用ContentValues进行构建将变得更加困难。当然,编写原始查询有点乏味。

    2. 如果有很多字符串/文本类型的数据,请考虑使用全文搜索(FTS3)创建虚拟表,这样可以运行更快的查询。你可以在谷歌上搜索速度的确切改善。

        4
  •  0
  •   Dave Jones    11 年前

    可以 找到一个替代方案,比如 unix无 SQLite VFS page !

    Normalization (关于表结构)也值得考虑(如果您还没有考虑的话),因为它倾向于在数据库中提供最小的数据表示;这是一个折衷方案,对于更多的CPU来说,I/O更少,而且在中型企业数据库中通常是值得考虑的(我最熟悉的类型),但恐怕我不知道这种折衷方案是否适用于像Android这样的小型平台。