0
  1. 背景 

    我是一名 iOS 开发人员,我们使用 CoreData,它使用 sqlite 数据库将数据存储在我们项目的磁盘中。几天前,我们的一位用户说在使用我们的 2.9.9 版本的应用程序时,他的界面在某些情况下不流畅。经过一番努力,我们终于发现这是由于从sqlite查询记录时效率低下造成的。但是在更新到最新版本 3.0.6 后,问题就消失了。 

  2. 分析

    (1)从sqlite查询记录时,SQL查询为

    '从 ZAPIOBJECT 中选择 * ZAPIOBJECTID = "xxx" AND Z_ENT == 34'

    在我们的应用程序的 2.9.9 版本中,sqlite 的表“ZAPIOBJECT”的架构显示

    '在 ZAPIOBJECT (Z_ENT) 上创建索引 ZAPIOBJECT_Z_ENT_INDEX;'

    '在 ZAPIOBJECT (ZAPIOBJECTID) 上创建索引 ZAPIOBJECT_ZAPIOBJECTID_INDEX;'

    查询计划显示

    '0 0 0 SEARCH TABLE ZAPIOBJECT AS t0 USING INDEX ZAPIOBJECT_Z_ENT_INDEX (Z_ENT=?)'</p>

    它使用效率较低的索引“Z_ENT”(1 行成本约为 4 秒)。

    (2)在我们的app 3.0.6版本中,SQL查询是一样的:

    '从 ZAPIOBJECT 中选择 * ZAPIOBJECTID = "xxx" AND Z_ENT == 34'

    但是sqlite的表'ZAPIOBJECT'的模式显示:

    '在 ZAPIOBJECT (Z_ENT) 上创建索引 ZAPIOBJECT_Z_ENT_INDEX;'

    '在 ZAPIOBJECT 上创建索引 Z_APIObject_apiObjectID (ZAPIOBJECTID COLLATE BINARY ASC);'</p>

    查询计划显示

    '0 0 0 搜索表 ZAPIOBJECT AS t0 使用索引 Z_APIObject_apiObjectID (ZAPIOBJECTID=?)'

    它使用更有效的索引“ZAPIOBJECTID”(1 行成本约为0.03 秒)。

    (3)表'ZAPIOBJECT'的记录总数约为130000,我们创建了distinct count大于90000的索引'ZAPIOBJECTID',而创建了distinct count只有20的索引'Z_ENT'由核心数据。

    (4)我们app的两个版本中sqlites的版本是相同的3.8.8.3。

  3. 问题

    (1)sqlite在查询记录时如何选择索引?在文档查询计划中,我了解到 sqlite 会自行选择最佳算法,但是在我们的案例中,选择不同的索引可以带来明显的效率。在我们的应用程序的两个版本中创建“ZAPIOBJECTID”之间的差异是否会导致sqlite采用不同的索引?

    (2) 系统版本低于iOS 11的用户好像会有这个问题,请问如何解决这个问题呢?我们可以使用 CoreData API 将 'ZAPIOBJECTID' 设置为指定索引吗?

4

1 回答 1

0

SQLite 使用导致估计 I/O 操作数量最少的索引。该估计的细节在每个版本中都会发生变化。

请参阅避免或修复查询计划程序问题的清单

于 2018-07-04T19:27:59.770 回答