我有一个“产品”实体的数据库,大约有 40k - 500k 个条目。我有一个允许用户滚动实体表的视图(我知道糟糕的设计,但这正是客户想要的)。
“产品”实体如下所示:
**Product:**
- part_number (string) (indexed)
- list_price (string)
- manufacturer_partNumber (string)
- productDescription (string)
- productID (string)
• inventory (NSManagedObject, 1..n)
- name (string)
- quantity (string)
• manufacturer (NSManagedObject, 1..1)
- name (string)
- manufacturerID (string)
起初,我NSFetchedResultsController
以标准方式创建了返回所有Product实体并设置了排序描述符part_number
。我跳过了所有的障碍来尝试加快获取速度:
- fetchBatchSize
- 索引属性
- 解释查询
这样做我只能将获取时间降低到大约 3.5 分钟。不好。
所以从 EXPLAIN QUERY 我看到很多时间都花在了获取inventory
andmanufacturer
实体上。合理但仍然不好。所以我决定只返回Product实体的一些属性而不是 who 的东西。
这是我正在获取的属性setPropertiesToFetch
- part_number (string) (indexed)
- list_price (string)
- photo (string)
- productID (string)
part_number
使用at 15设置排序描述符fetchBatchSize
。这将获取时间缩短到约 40 秒。还是不好。
我知道有人会在这里问我是如何设置的NSFetchedResultsController
:
- (NSFetchedResultsController *)fetchedResultsControllerWithCacheName:(NSString*)cacheName {
[NSFetchedResultsController deleteCacheWithName:cacheName];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Product" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"part_number" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:15];
[fetchRequest setResultType:NSDictionaryResultType];
[fetchRequest setReturnsDistinctResults:YES];
[fetchRequest setPropertiesToFetch:@[@"part_number", @"list_price", @"photo", @"productID"]];
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil
cacheName:cacheName];
return theFetchedResultsController;
}
我还能做些什么来加快速度吗?
我有一个可能真的很hacky的想法是使用 NSFetchedResultsController 进行某种类型的延迟加载(是的,我知道它应该处理它)。我还没有完全考虑到这一点,但将其设置setFetchLimit
为 100 并使用 NSPredicate 在 last 之后加载内容part_number
。这可能只是耗时。