对于我的iPhone应用程序,我为Core Data设置了一个数据模型。它包含一个实体Words
,其属性为language : String
,length : Integer16
和word : String
。
我用一个单词列表(200k项目)预填充模型的SQLite数据库,使用相同的数据模型编写单独的iPhone应用程序,并将填充的数据库复制到主应用程序。
现在使用NSFetchedRequest我可以随意查询托管对象,但结果很慢。我使用以下方法:
- (NSString *)getRandomWordLengthMin:(int)minLength max:(int)maxLength
{
NSString *word = @"";
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Words"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSString *predicateString = @"length >= %d AND length <= %d";
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString,
minLength, maxLength];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
int entityCount = [context countForFetchRequest:fetchRequest error:&error];
[fetchRequest setFetchLimit:1];
if(entityCount != 0)
{
[fetchRequest setFetchOffset:arc4random()%entityCount];
}
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if([fetchedObjects count] != 0)
{
Words * test = [fetchedObjects objectAtIndex:0];
word = [NSString stringWithFormat:@"%@", [test word]];
}
return word;
}
使用SQLite编辑器我已经在zLength列上手动设置了索引,但这并没有带来任何加速。瓶颈在哪里?
修改
我发现获得int entityCount = ...
的速度很慢。但即使获取所有对象然后选择一个随机单词也很慢:
Words * test = [fetchedObjects objectAtIndex:arc4random()%[fetchedObjects count]];
答案 0 :(得分:3)
你实际上在这里运行两次提取,一次获取获取计数,然后一次获取实际对象。这会减慢速度。
你的谓词是“倒退”。复合谓词评估第一个表达式,例如length >= %d
,然后评估第二个,例如length <= %d
仅针对第一个结果。因此,您应该首先进行消除大多数对象的测试。在这种情况下,length <= %d
可能会消除更多对象,因此它应该首先出现在谓词中。
由于您实际上不需要整个Words
托管对象而只需要word
字符串,因此可以将获取返回类型设置为NSDictionaryResultType
,然后将属性设置为fetch to只是word
属性。这将大大加快速度。
这里的部分问题是Core Data旨在管理结构化对象图,并且您正在使用随机/非结构化图形,因此您正在削减Core Data的优化。
答案 1 :(得分:1)
不要使用SQLite编辑器编辑Core Data存储的SQLite后备存储。数据库的内部是私有的,可能会发生变化。
而是转到Xcode中的模型编辑器,只需勾选要索引的实体属性的“索引”选项。
不确定但是这个谓词可能更容易优化:
NSString *predicateString = @"length BETWEEN (%d, %d)";