背景
我是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上创建索引ZAPIOBJECT_Z_ENT_INDEX(Z_ENT);'
'在ZAPIOBJECT上创建索引ZAPIOBJECT_ZAPIOBJECTID_INDEX(ZAPIOBJECTID);'
并且查询计划显示
'0 0 0使用索引ZAPIOBJECT_Z_ENT_INDEX(Z_ENT =?)将表ZAPIOBJECT搜索为t0”
使用效率较低的索引“ Z_ENT”( 1行的成本约为4秒)。
(2)在我们的应用程序的3.0.6版本中,SQL查询是相同的:
'SELECT * FROM ZAPIOBJECT WHERE ZAPIOBJECTID =“ xxx” AND Z_ENT == 34'
但是sqlite的表“ ZAPIOBJECT”的架构显示:
‘在ZAPIOBJECT上创建索引ZAPIOBJECT_Z_ENT_INDEX(Z_ENT);’
‘在ZAPIOBJECT上创建索引Z_APIObject_apiObjectID(ZAPIOBJECTID COLLATE BINARY ASC);’
并且查询计划显示
‘0 0 0使用索引Z_APIObject_apiObjectID(ZAPIOBJECTID =?)作为t0搜索表ZAPIOBJECT”
使用更高效的索引“ ZAPIOBJECTID”(每1轮费用约0.03s w)。
(3)表“ ZAPIOBJECT”中的记录总数约为130000,由我们创建了唯一计数大于90000的索引“ ZAPIOBJECTID”,而仅创建唯一计数的索引“ Z_ENT” 20由CoreData创建。
(4)我们应用程序的两个版本中sqlite的版本相同,即3.8.8.3。
问题
(1)SQLite在查询记录时如何选择索引?在文档Query Planning中,我了解到sqlite会自行选择最佳算法,但是在我们这种情况下,选择不同的索引会导致明显的效率。在两个版本的应用程序中创建“ ZAPIOBJECTID”之间的区别导致sqlite采用不同的索引?
(2)似乎那些系统版本低于iOS 11的用户会遇到此问题,那么我们如何为他们解决此问题?我们可以使用CoreData API将“ ZAPIOBJECTID”设置为指定的索引吗?
答案 0 :(得分:0)
SQLite使用导致估计的I / O操作最少的索引。 估算的详细信息在每个版本中都会发生变化。