我正在使用 NSFetchedResultsController 查询一个包含大约 250,00 个英文单词的非常简单的数据库。我使用 [NSCompoundPredicate andPredicateWithSubPredicates] 构造以下谓词:
"word LIKE '*a*' AND word LIKE '*b*' AND word LIKE '*c*' AND word LIKE '*d*'"
当我通过调用 [NSFetchedResultController alloc] initWithFetchRequest:...] 运行查询时,运行大约需要 8 秒。
我可以使用 sqlite3 在完全相同的数据库上运行等效查询:
"Select word from words where word LIKE '%a%' AND word LIKE '%b%' ..."
CPU时间约为0.01秒。
使用 LIKE 或使用 NSPredicate 或 NSFetchedResultsController 有区别吗?
更新
目前,对象模型尽可能简单,由单个Word对象组成,具有三个属性
NSString * word
NSString * sortedWord
NSInteger 长度。
这是 Instruments - Time Profiler 的屏幕截图(我不确定从 Instruments 共享数据的更好方法),它显示(我认为)大部分时间都花在 [_NSPredicateUtiltiesDoRegexForString:Pattern:likeProtect:flags:语境:]。
http://www.mckaydalton.com/images/instruments.jpg
此外,这是 SQLDebug 输出:
CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZLENGTH, t0.ZSORTEDSTRING, t0.ZWORD FROM ZWORD t0 WHERE ( NSCoreDataLike( t0.ZWORD, ?, 0) AND NSCoreDataLike( t0.ZWORD, ?, 0) ) ORDER BY t0.ZWORD
CoreData:注解:sql连接获取时间:10.7353s
CoreData:注释:总提取执行时间:10.7439 秒,24891 行。
这里使用“原始”sqlite3 对同一数据库进行相同的选择:
SELECT 0, Z_PK, Z_OPT,ZSORTEDSTRING, ZWORD FROM ZWORD WHERE ZWORD LIKE '%a%' AND ZWORD LIKE '%b%' ORDER BY ZWORD;
CPU时间:用户0.377206 sys 0.054738
因此,在我看来,NSCoreDataLike 的行为与 sqlite 内置的“LIKE”非常不同。这不是一个主要问题,因为我可以只使用 C-api 到 sqlite(尽管我想将项目保留在 CoreData 中,因为它会变得更大,如果可能的话)或使用 CONTAINS 而不是 LIKE (尽管这将需要更改应用程序逻辑),但很高兴了解发生了什么