我正在使用子查询谓词对核心数据托管对象上下文执行提取,以提取要放在 map 上的实体。实体由相关实体上的属性过滤,因此使用子查询。子查询的谓词因用户选择的过滤条件而异。我发现这些子查询谓词中最简单的一个是导致提取所需的时间比预期的要长。
我的简化对象图如下所示:
Entity <-->> RelatedEntity <<--> FilterRelationship
-latitude
-longitude
NSFetchRequest
上的谓词如下所示:
(latitude > #.# AND latitude < #.# AND longitude > #.# AND longitude < #.#) AND SUBQUERY(relatedEntities, $relatedEntity, $relatedEntity.filterRelationship IN { JUST_ONE_HERE }).@计数 > 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 > ? AND t0.ZLONGITUDE < ?) AND (SELECT COUNT(t1.Z_PK) FROM ZRELATEDENTITY t1 WHERE (t0.Z_PK = t1.ZENTITY AND ( t1.ZFILTERRELATIONSHIP IN (?) )) ) > ?) ORDER BY ... LIMIT 50
CoreData: annotation: sql connection fetch time: 903.6430s
CoreData: annotation: total fetch execution time: 903.6458s for 50 rows.
和
CoreData: sql: SELECT t0.Z_ENT, t0.Z_PK, t0.Z_OPT, ... FROM ZENTITY t0 WHERE (( t0.ZLATITUDE > ? AND t0.ZLATITUDE < ? AND t0.ZLONGITUDE > ? AND t0.ZLONGITUDE < ?) AND (SELECT COUNT(t1.Z_PK) FROM ZRELATEDENTITY t1 WHERE (t0.Z_PK = t1.ZENTITY AND ( t1.ZFILTERRELATIONSHIP IN (?,?) )) ) > ?) ORDER BY ... LIMIT 50
CoreData: annotation: sql connection fetch time: 1.7181s
CoreData: annotation: total fetch execution time: 1.7216s for 50 rows.
我用 ...
删除了不重要的部分,并重命名了实体以明确它们是什么。但正如您所看到的,查询是根据 map 上的经度和纬度获取类型为 Entity
的实体,以及基于相关实体 RelatedEntity
的子查询和谓词将这些相关实体上的关系与指定的 FilterRelationship
实体匹配。
在子查询谓词的集合中只有一个 FilterRelationship
实体的简单情况下,提取大约需要 15 分钟。
上述两个查询的唯一区别是第二个查询在子查询谓词的集合中有两个 FilterRelationship
实体。第二个示例在 2 秒内完成。
数据库包含~22,000 个Entity
、~5,000 个RelatedEntity
和3 个FilterRelationship
实体。
我也尝试了相同的谓词,除了使用相等谓词代替 IN
一组一个对象。
(latitude > #.# AND latitude < #.# AND longitude > #.# AND longitude < #.#) AND SUBQUERY(relatedEntities, $relatedEntity, $relatedEntity.filterRelationship == JUST_ONE_HERE).@count > 0
这个谓词有同样的慢取结果。
被搜索的 Entity
集合越小,子查询谓词提取执行得越快。因此,通过放大 map 的一小块区域并让纬度/经度谓词过滤掉正在搜索的 Entity
,尽管单个 FilterRelationship的速度很慢,但获取执行速度更快
。大约 15 分钟的数字是在 map 上一直放大时测量的,过滤数据库中的所有 Entity
。
编辑:
我更新了对象图以反射(reflect)第一个关系,Entity
到 RelatedEntity
是一对多的关系。第二种关系 RelatedEntity
到 FilterRelationship
是多对一关系。
在缩小导致应用程序中这些缓慢获取的谓词的特定部分之后,我创建了一个解决方法,始终确保在我的谓词中设置的 FilterRelationship
中至少有两个实体。为了避免与这个额外的 FilterRelationship
匹配任何东西,我尝试将 NSNull
添加到集合中。果然,这成功了!
如果用户选择的搜索条件仅在谓词中指定一个 FilterRelationship
,我只需将 [NSNull null]
添加到子查询谓词的集合中,然后在秒而不是几十分钟。
我仍然不知道为什么这是一个问题。这似乎是 Core Data 或 SQLite 中的错误。
关于ios - 当子查询谓词仅包含一个实体时,Core Data SQLite 查询呈指数级变慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26559487/
欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) | Powered by Discuz! X3.4 |