【发布时间】:2018-12-11 07:43:04
【问题描述】:
-
背景
我是一名 iOS 开发人员,我们使用 CoreData,它使用 sqlite 数据库将数据存储在我们项目的磁盘中。几天前,我们的一位用户说在使用我们的 2.9.9 版本的应用程序时,他的界面在某些情况下不流畅。经过一番努力,我们终于发现这是由于从sqlite查询记录时效率低下造成的。但是在更新到最新版本 3.0.6 后,问题就消失了。
-
分析
(1)从sqlite查询记录时,SQL查询为
'SELECT * FROM ZAPIOBJECT WHERE 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=?)'
使用效率较低的索引“Z_ENT”(1 行成本约为 4 秒)。
(2)在我们的app 3.0.6版本中,SQL查询是一样的:
'SELECT * FROM ZAPIOBJECT WHERE ZAPIOBJECTID = "xxx" AND Z_ENT == 34'
但是sqlite的表'ZAPIOBJECT'的模式显示:
'在 ZAPIOBJECT (Z_ENT) 上创建索引 ZAPIOBJECT_Z_ENT_INDEX;'
‘在 ZAPIOBJECT 上创建索引 Z_APIObject_apiObjectID (ZAPIOBJECTID COLLATE BINARY ASC);’
查询计划显示
‘0 0 0 SEARCH TABLE ZAPIOBJECT AS t0 USING INDEX Z_APIObject_apiObjectID (ZAPIOBJECTID=?)’
它使用更高效的索引“ZAPIOBJECTID”(1 ro 成本约为 0.03 秒w)。
(3)表'ZAPIOBJECT'的记录总数约为130000条,我们创建了distinct count大于90000的索引'ZAPIOBJECTID',而distinct计数的索引'Z_ENT'只有20 由 CoreData 创建。
(4)我们应用的两个版本中sqlites的版本是相同的3.8.8.3。
-
问题
(1)sqlite在查询记录时如何选择索引?在Query Planning 文档中,我了解到 sqlite 会自行选择最佳算法,但是在我们的案例中,选择不同的索引会带来明显的效率。在我们的应用程序的两个版本中创建“ZAPIOBJECTID”之间的差异是否会导致sqlite采用的不同索引?
(2) 系统版本低于iOS 11的用户似乎会出现这个问题,请问如何为他们解决这个问题?我们可以用 CoreData API 将“ZAPIOBJECTID”设置为指定索引吗?
【问题讨论】:
标签: ios core-data sqlite isqlquery