几点建议。如果获取21,500行需要5秒钟,那么你可能在使用旧设备,比如3G或原始iPhone。这些设备的内存和I/O性能很慢。你需要非常小心地处理数据,避免将所有数据读入内存并进行不必要的I/O操作。你可能会发现-setFetchBatchSize特别有用。如果你在3GS上运行,10-20千行是可管理的,但需要小心。如果你在iPad或iPhone4上运行,这应该不是什么问题。
你不需要创建自己的UUID,除非与外部系统(如服务器)进行交互。每个托管对象都有一个objectID,它是其主键的OOP表示形式。只需传递objectID,并执行像@"self = %@"或@"self IN %@"这样的查询来通过其ID或ID数组搜索对象。你还可以使用-existingObjectWithID:error:方法通过其objectID查找单个对象,这比具有通用谓词的通用获取请求更快。
验证索引是否按预期使用的最佳方法是在模拟器中使用可执行参数
-com.apple.CoreData.SQLDebug 1
运行应用程序,它会记录生成的SQL到控制台。你应该会看到一些以t0.uuid == ?结尾的东西。
你可以将该SQL select语句输入SQLite的explain查询工具中运行。在模拟器中对db文件运行/usr/bin/sqlite3,然后执行
.explain ON
explain query plan copythatsqllinehere
如果它缺少“with index”,那么你的Core Data存储创建方式存在问题(你确定模型被标记为索引uuid吗?)或者存在其他获取请求问题。
这真是令人惊讶。如果我想逐个获取存储中的每个对象,那将需要近4.5小时!
我想你可以用最痛苦的方式之一做到这一点。或者你可以使用-setFetchBatchSize:,快速地迭代处理对象的批次。
此外,请记住,每次获取都会与数据库进行I/O以保持与任何其他线程保存的内容同步。获取不是某种神奇的字典查找。执行最小单元的I/O所需的时间有一个下限。你需要将每个单独的I/O请求分摊来获得最佳性能。你将需要权衡读取过多内存而造成的问题。
如果您继续遇到问题,请在bugreport.apple.com上报告错误。