sqlite在查询记录时如何选择索引?

时间:2018-07-03 05:07:27

标签: ios core-data sqlite isqlquery

  1. 背景

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

  2. 分析

    (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。

  3. 问题

    (1)SQLite在查询记录时如何选择索引?在文档Query Planning中,我了解到sqlite会自行选择最佳算法,但是在我们这种情况下,选择不同的索引会导致明显的效率。在两个版本的应用程序中创建“ ZAPIOBJECTID”之间的区别导致sqlite采用不同的索引?

    (2)似乎那些系统版本低于iOS 11的用户会遇到此问题,那么我们如何为他们解决此问题?我们可以使用CoreData API将“ ZAPIOBJECTID”设置为指定的索引吗?

1 个答案:

答案 0 :(得分:0)

SQLite使用导致估计的I / O操作最少的索引。 估算的详细信息在每个版本中都会发生变化。

请参见Checklist For Avoiding Or Fixing Query Planner Problems