【问题标题】:Core Data SQLite query exponentially slower when subquery predicate contains only one entity当子查询谓词仅包含一个实体时,Core Data SQLite 查询呈指数级变慢
【发布时间】:2014-12-20 23:23:12
【问题描述】:

我正在使用子查询谓词对核心数据托管对象上下文执行提取,以提取要放在地图上的实体。实体由相关实体上的属性过滤,因此使用子查询。子查询的谓词因用户选择的过滤条件而异。我发现这些子查询谓词中最简单的一个是导致提取所需的时间比预期的要长。

我的简化对象图如下所示:

Entity  <-->>  RelatedEntity  <<-->  FilterRelationship
-latitude
-longitude

NSFetchRequest 上的谓词如下所示:

(latitude &gt; #.# AND latitude &lt; #.# AND longitude &gt; #.# AND longitude &lt; #.#) AND SUBQUERY(relatedEntities, $relatedEntity, $relatedEntity.filterRelationship IN { JUST_ONE_HERE }).@count &gt; 0

JUST_ONE_HERE 表示当子查询谓词的这部分集合中只有一个实体时,这是查询所需时间呈指数增长的地方。如果我在这个集合中有多个实体,查询将正常执行。

使用启动参数-com.apple.CoreData.SQLDebug 1,我记录了以下内容:

CoreData: sql: SELECT t0.Z_ENT, t0.Z_PK, t0.Z_OPT, ... FROM ZENTITY t0 WHERE (( t0.ZLATITUDE > ? AND t0.ZLATITUDE ? AND t0.ZLONGITUDE (?) )) > ?) ORDER BY . 限制 50

CoreData:注解:sql连接获取时间:903.6430s

CoreData:注释:总提取执行时间:903.6458s for 50 行。

CoreData: sql: SELECT t0.Z_ENT, t0.Z_PK, t0.Z_OPT, ... FROM ZENTITY t0 WHERE (( t0.ZLATITUDE > ? AND t0.ZLATITUDE ? AND t0.ZLONGITUDE (?,?) )) > ?) ORDER BY ...限制 50

CoreData:注解:sql连接获取时间:1.7181s

CoreData:注释:总提取执行时间:50 行 1.7216 秒。

我用... 删除了不重要的部分,并重命名了实体以明确它们是什么。但正如您所看到的,该查询正在获取类型为 Entity 的实体,基于它们在地图上的经度和纬度,以及基于相关实体 RelatedEntity 的子查询以及将这些相关实体上的关系与指定FilterRelationship 实体。

在子查询谓词的集合中只有一个 FilterRelationship 实体的简单情况下,提取大约需要 15 分钟。

上述两个查询之间的唯一区别是第二个查询在子查询谓词的集合中有两个FilterRelationship 实体。第二个示例在 2 秒内完成。

该数据库包含 ~22,000 个Entity、~5,000 个RelatedEntity 和 3 个FilterRelationship 实体。

我也尝试了同样的谓词,除了使用相等谓词代替 IN 一组一个对象。

(latitude &gt; #.# AND latitude &lt; #.# AND longitude &gt; #.# AND longitude &lt; #.#) AND SUBQUERY(relatedEntities, $relatedEntity, $relatedEntity.filterRelationship == JUST_ONE_HERE).@count &gt; 0

这个谓词有同样的慢取结果。

搜索的Entitys 集越小,子查询谓词提取执行的速度就越快。因此,通过放大地图的一小块区域并让纬度/经度谓词过滤掉正在搜索的Entitys,尽管单个FilterRelationship 的速度很慢,但获取执行速度更快。大约 15 分钟的数字是在地图上一直放大时测量的,过滤数据库中的所有 Entitys。

编辑:

我更新了对象图以反映第一个关系 EntityRelatedEntity 是一对多关系。第二个关系,RelatedEntityFilterRelationship 是多对一关系。

【问题讨论】:

    标签: ios objective-c sqlite core-data subquery


    【解决方案1】:

    在缩小导致我的应用程序中这些缓慢获取的谓词的特定部分之后,我创建了一个解决方法,始终确保我的谓词中的FilterRelationship 集中至少有两个实体。为了避免与这个额外的FilterRelationship 匹配任何东西,我尝试将NSNull 添加到集合中。果然,这成功了!

    如果用户选择的搜索条件只在谓词中指定了一个FilterRelationship,我只需将[NSNull null] 添加到子查询谓词的集合中,提取就会在几秒钟内而不是几十分钟内执行。

    我仍然不知道为什么这是一个问题。这似乎是 Core Data 或 SQLite 中的错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-29
      • 1970-01-01
      • 1970-01-01
      • 2021-09-05
      • 2015-03-20
      • 1970-01-01
      • 2013-08-05
      • 1970-01-01
      相关资源
      最近更新 更多