我正在研究一個iOS閃存卡風格的學習應用程序,它在加載時需要從Core Data獲取一堆數據。但是,我需要的數據是實體的一個相當特定的子集,基於用戶設置,所以有多個謂詞涉及測試等價性。我發現這些提取速度非常慢,基於對SQLite的研究,我認爲索引在這裏是一個不錯的選擇。使用核心數據時可能存在複雜索引嗎?
現在,我明白(主要是從閱讀其他stackoverflow問題)SQLite和核心數據是兩個不同的,基本上正交的東西,不應該混淆。但我的理解是,你應該通過Core Data來完成任何類型的數據庫工作和調整;在應用中優化或設計對象永久性時,您不應該嘗試繞過並直接與SQLite合作。
但我唯一可以找到的核心數據中的索引是一個「索引」複選框模型中的每個屬性。這只是沒有做我想要的那種優化。
這裏的讀取請求,目前:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"SKUserItem" inManagedObjectContext:context];
fetchRequest.entity = entity;
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"next" ascending:YES] autorelease];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:6];
[predicates addObject:[NSPredicate predicateWithFormat:@"next < %f", now() + (60.0*60.0*24.0)]];
[predicates addObject:[NSPredicate predicateWithFormat:@"next > %f", nextOffset]];
[predicates addObject:[NSPredicate predicateWithFormat:@"user == %@", user]];
[predicates addObject:[NSPredicate predicateWithFormat:@"langRaw == %d", lang]];
NSArray *stylePredicates = [NSArray arrayWithObjects:[NSPredicate predicateWithFormat:@"styleRaw == %d", SK_SIMP_AND_TRAD], [NSPredicate predicateWithFormat:@"styleRaw == %d", self.style], nil];
[predicates addObject:[NSCompoundPredicate orPredicateWithSubpredicates:stylePredicates]];
if([self.parts count] == 4 || (self.lang == SK_JA && [self.parts count] == 3))
; // don't have to filter by parts; they're studying all of them
else {
NSMutableArray *partPredicates = [NSMutableArray arrayWithCapacity:[self.parts count]];
for(NSString *part in self.parts)
[partPredicates addObject:[NSPredicate predicateWithFormat:@"partRaw == %d", partCode(part)]];
[predicates addObject:[NSCompoundPredicate orPredicateWithSubpredicates:partPredicates]];
}
NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];
fetchRequest.predicate = compoundPredicate;
所以基本上這是什麼取確實是有點明年(當給定項目到期時間)和用戶名過濾,語言正在研究,風格之中學習(中文簡體和傳統)和正在研究的部分(寫作,語調,閱讀或定義),並且只在「下一個」範圍內進行。下面是我從調整和擺弄中學到的東西的簡短列表:
- 它總是掃描整個表格,或者似乎是。雖然下一個索引,即使我強迫它搜索範圍,我知道將不會返回任何內容,它仍然需要幾秒鐘才能完成獲取。
- 謂詞謂詞,任何數量的謂詞都會使這個變慢。如果我刪除了一些,但不是全部,它是一樣慢。如果我刪除所有謂詞(從而打破應用程序),那麼速度會更快。
- 速度在很大程度上取決於表中總共有多少個UserItems。有更多的項目,這是更慢。有些人可能擁有數以萬計的項目,那麼這個獲取可能需要10秒才能完成。這導致了我的應用程序暫停尷尬。
- 下一個值的上限並不是因爲我們需要它,而是因爲它加快了取回的速度。
- 讓查詢返回字典中的屬性子集(而不是整個託管對象)並且懶懶地提取其餘部分的速度會更快,但仍然不夠快。
我來自Google App Engine這裏,所以我習慣了他們在那裏提供的索引。基本上我想要這種索引,但通過核心數據應用於SQLite。我發現有關在SQLite中添加索引的信息,我會希望的,但通過核心數據做這種索引,我找不到任何信息。
我還沒有遇到核心數據,顯示了1個謂詞性能問題,但如果你只談論項目數以萬計,你可能使用非基於SQL的核心數據存儲找到更好的性能。例如,二進制存儲類型可能會更快。 –
感謝您的建議。我試了一下,但在我的3GS上測試顯示,二進制存儲類型無法處理那麼多的數據。在程序因使用太多內存而崩潰之前,我加載了一個擁有30,000個以上項目的帳戶。可能是因爲SKUserItem實體中有26個屬性。 –
啊,那太糟糕了。我真的不明白爲什麼第一點是屬於索引的情況。 –