当前位置: 首页 > 面试题库 >

Android SQLite在复杂查询中的性能

艾晋
2023-03-14
问题内容

假设我有这种查询

String sql = "SELECT s.team_id, s.team_name, s.gp, s.w, s.t, s.l, s.go, s.ga, s.score, s.p FROM "
           + "(SELECT team_id, team_name, SUM (gp) gp, SUM (w) w, SUM (t) t, SUM (l) l, SUM (GO) go, SUM (GA) ga, SUM (GO)- SUM (GA) score, SUM (2*w+t) p FROM "
           + "(SELECT t._id team_id, t.name team_name, COUNT(CASE WHEN score_home IS NOT NULL THEN 1 END) gp, COUNT (CASE WHEN score_home > score_away THEN 1 END) w,"
           + " COUNT (CASE WHEN score_home = score_away THEN 1 END) t, COUNT (CASE WHEN score_home < score_away THEN 1 END) l,"
           + " SUM (score_home) go, SUM (score_away) ga"
           + " FROM team_table t LEFT OUTER JOIN match_table m ON m.team_home = t._id"
           + " WHERE t.tournament_id = ? GROUP BY t._id, t.name"
           + " UNION ALL"
           + " SELECT t._id team_id, t.name team_name, COUNT(CASE WHEN score_away IS NOT NULL THEN 1 END) gp, COUNT (CASE WHEN score_home < score_away THEN 1 END) w,"
           + " COUNT (CASE WHEN score_home = score_away THEN 1 END) t, COUNT (CASE WHEN score_home > score_away THEN 1 END) l,"
           + " SUM (score_away) go, SUM (score_home) ga"
           + " FROM team_table t LEFT OUTER JOIN match_table m ON m.team_away = t._id"
           + " WHERE t.tournament_id = ? GROUP BY t._id, t.name)"
           + " GROUP BY team_id, team_name) s"
           + " ORDER BY s.p DESC, s.score DESC, s.go ASC";

然后像这样使用

Cursor cursor = database.rawQuery(sql, args);

cursor.moveToFirst();
while (!cursor.isAfterLast()) {
    TeamStats stat = new TeamStats();

    stat.setTeamId(cursor.getLong(0));
    stat.setTeamName(cursor.getString(1));
    stat.setGamesPlayed(cursor.getInt(2));
    stat.setWins(cursor.getInt(3));
    stat.setTies(cursor.getInt(4));
    stat.setLoses(cursor.getInt(5));
    stat.setGoalsOwn(cursor.getInt(6));
    stat.setGoalsAgaist(cursor.getInt(7));
    stat.setScore(cursor.getInt(8));
    stat.setPoints(cursor.getInt(9));

    stats.add(stat);
    cursor.moveToNext();
}
cursor.close();

因此,它从许多表中选择值,执行一些操作等。如您所见,查询非常复杂(非常难调试),并且性能似乎不如我预期的好。我的问题是:

  1. 我可以使用某种准备好的语句来提高性能吗?
  2. 执行更简单的查询并使用一些自定义代码手动处理它们会更快吗?

问题答案:

如果您是我,则将您的sqlite数据库复制到主机,然后尝试在某些SQLite
GUI中手动执行它,同时用?您拥有的实际变量值替换绑定变量()。对于Windows上的GUI,我真的很喜欢SQLite Expert
Personal
,而在Linux sqliteman上非常不错。

在调试SQL(在命令行或GUI中)时,请确保通过在EXPLAIN和/或下运行它们来分析SQL语句EXPLAIN QUERY PLAN。当心表扫描。您应该尝试通过添加索引来消除昂贵的扫描。但是不要索引所有内容-
可能会使情况更糟。通常,通过使用复合(多列)索引,可以大大提高性能。注意,在任何给定的表上,SQLite不能仅使用一个索引(在运行给定的SQL语句时)-因此,明智地选择索引。(另请参阅查询计划中的基本说明。)

为了解决您对Java和SQLite中数据处理的担忧-我认为 针对关系数据进行
完全优化(使用适当的索引等)的SQLite查询将(几乎)总是比在Java中手动处理此数据要快。在您的情况下,这尤其必须正确-您的所有数据基本上都是关系型的。

不过,请注意以下几点:默认情况下,使用Java的Android APK可能比SQLite拥有更多的内存访问权限-
您可能想使用setMaxSqlCacheSize()(相当于PRAGMA cache_size)来增加数据库的SQLite缓存大小。Android的默认值为10(最大为100),请尝试增加该值,看看是否对您的查询有所影响。请注意,此设置的桌面SQLite默认默认值更高-2000。



 类似资料:
  • 我有这个: 如何从hashlist中排除“item”?打破了我的头。Linq不想对我开放。

  • 问题内容: 我正在将MS-Access 2003与查询创建者一起使用。我从一个表()中选择所有内容,然后从另一表()中选择一个特定行()。我想从第二个表中选择另一行并将其连接起来。 查询 该查询的确在ID(字段)与where匹配的地方添加了字段。它像一种魅力。但是,我想在结果中添加另一行。我想获得行所在的位置(该部分实际上在工作)和行所在的位置。我将得到2行,并且当我要求()时,我希望将这两行连接

  • 我一直在使用关系数据库,最近决定将性能关键服务从SQL服务器迁移到Tarantool,希望利用内存中的快速搜索和处理。在计划迁移时,我有几个问题。 我有一个包含大约一百万条记录的表,其中包含定价信息,这意味着我主要处理的是数字和UUID。首先,我需要运行一个包含多个条件的select来获取数据的子集,如 Q1:在Lua中运行这样一个查询的策略是什么?我是为谓词中的每个字段创建索引,还是可以使用一个

  • 问题内容: 我正在尝试查询Google BigQuery公共Reddit数据集。我的目标是使用Jaccards’Index来计算子reddit的相似性,该索引的定义如下: 我的计划是在2016年8月按评论数选择前N = 1000个子项,然后计算其笛卡尔积,以得到形状中所有子项的组合。 然后使用这些组合的行来查询subreddit1和subreddit 2之间的用户并集以及交集。 我到目前为止的查询

  • 问题内容: 表Words_Learned包含用户已知的所有单词以及 单词学习的顺序。它具有3列:1)单词ID和2)用户ID,以及3) 单词学习的顺序。 表中Article包含文章。它具有3列:1)文章ID,2) 唯一字数和3)文章内容。 该表Words包含每篇文章中包含的所有唯一单词的列表。 它有2列1)单词ID和2)文章ID 数据库图如下/ 在此处输入图片说明 您可以从此处下载数据库代码:htt

  • 问题内容: 我有以下ManyToMany映射。 我想检索与Classe2实体有关系的所有Class1实体,其中class2Id = 1和class2Id = 2和class2Id = 3。{1,2,3} 或者,要过滤在其class2列表上具有的Classe1实体,请使用具有以下值的Class2实体:class2Id = 1和class2Id = 2和class2Id = 3 例如: 如果在联接表上