背景
我是一名 iOS 开发人员,我们使用 CoreData,它使用 sqlite 数据库将数据存储在我们项目的磁盘中。几天前,我们的一位用户说在使用我们的 2.9.9 版本的应用程序时,他的界面在某些情况下不流畅。经过一番努力,我们终于发现这是由于从sqlite查询记录时效率低下造成的。但是在更新到最新版本 3.0.6 后,问题就消失了。
分析
(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。
问题
(1)sqlite在查询记录时如何选择索引?在文档查询计划中,我了解到 sqlite 会自行选择最佳算法,但是在我们的案例中,选择不同的索引可以带来明显的效率。在我们的应用程序的两个版本中创建“ZAPIOBJECTID”之间的差异是否会导致sqlite采用不同的索引?
(2) 系统版本低于iOS 11的用户好像会有这个问题,请问如何解决这个问题呢?我们可以使用 CoreData API 将 'ZAPIOBJECTID' 设置为指定索引吗?
问问题
109 次
1 回答
0
SQLite 使用导致估计 I/O 操作数量最少的索引。该估计的细节在每个版本中都会发生变化。
请参阅避免或修复查询计划程序问题的清单。
于 2018-07-04T19:27:59.770 回答