0

NSFetchedResultsController と、フェッチされた結果コントローラーがフェッチする必要がある Core Data に大量のデータが格納されています。最終的にフェッチされるアイテムは約 46,000 です。問題は、フェッチに 8 秒以上かかることと、メイン スレッドでフェッチする必要があるため、その間ずっと UI がフリーズしていることです。これをスピードアップするために何かできることがあるかどうか疑問に思っていましたか?

オブジェクトを作成日順に並べ替えています。フェッチ リクエストのバッチ サイズは 100 で、述語はそれほど複雑ではありません。UID、タイプ、および所有者の UID によってオブジェクトをフィルタリングします。

ユーザーは検索できるため、フェッチ述語が変更されるため、フェッチ述語が変更されるたびに単純に削除される場合、フェッチされた結果コントローラーにキャッシュを持っていても無意味に思えます。

これは、コア データ内のオブジェクトの数に直接関連しています。これは、オブジェクトが少ないアカウントに切り替えると、フェッチ時間が大幅に短縮されるためです。(6000 個のオブジェクトには 1 秒もかかりません)。これをよりスケーラブルにする方法はありますか? 私のコードは次のとおりです。

- (NSFetchRequest *)getFetchRequest
{
    NSFetchRequest *fetchRequest = [NSFetchRequest requestWithEntityName:@"Photo"];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
    [sortDescriptor release];
    [fetchRequest setPredicate:[self getFetchPredicates]];
    [fetchRequest setFetchBatchSize:100];
    return fetchRequest;
}

- (NSPredicate *)getFetchPredicates {
    NSMutableArray *predicates = [NSMutableArray arrayWithObjects:
                                  [NSPredicate predicateWithFormat:@"life_uid == %@",[[LoginManager shared] currentLifeUID]],
                                  [NSPredicate predicateWithFormat:@"(type == %@) OR (type == %@)", TLTypeImage, TLTypeVideo],
                                  [NSPredicate predicateWithFormat:@"(ANY stories.permission.owner_person_uid == %@ OR stories.@count == 0)", [[LoginManager shared] currentPersonUID]],
                                  nil];
    NSArray *filteredMomentIDs = [[self searchTerms] objectForKey:TLLibraryViewControllerSearchTermsPhotoIDsKey];
    if ([filteredMomentIDs count] > 0 && [self searchMode] == kTLLibrarySearchModeTag)
    {
        [predicates addObject:[NSPredicate predicateWithFormat:@"uid in %@", filteredIDs]];
    }
    return [NSCompoundPredicate andPredicateWithSubpredicates:predicates];
}
4

2 に答える 2

3

すべての属性が文字列であることを (コメントで) 説明しているので、状況を改善するのに苦労するかもしれません。そのフェッチで多くの文字列比較を行っています。最初の 2 つの述語で 46,000 レコードに少なくとも 3 を掛けたものに加えてstories、平均で関係がいくつあるかによってさらに多くの比較が行われます。これがパフォーマンスの問題の主な理由です。多くの文字列比較を行うとボトルネックになります。

役立つかもしれないいくつかのこと:

  • あなたが見ている3番目の述語では@"(ANY stories.permission.owner_person_uid == %@ OR stories.@count == 0)"。述部は左から右に評価されます。数値比較は文字列比較よりも高速であるため、@count最初にチェックを入れてください。true の場合、後半を評価する必要はなく、多くの文字列比較をスキップします。
  • 左から右のことは、NSPredicateインスタンスの順序にも適用されます。おそらく、データがどのように見えるかある程度はわかっているでしょう。最も制限の厳しい述語 (つまり、最大数のオブジェクトが通過しない述語) がリストの最初の述語であることを確認してください。次に、2 番目に制限的なものなどです。述語を一緒に and-ing しているため、インスタンスが失敗し、最初の述語を他の述語と照合する必要はありません。述語チェーンのできるだけ早い段階でオブジェクトを除外します。

おそらく最も簡単な方法は、3 番目の述語の順序を変更し、それをリストの先頭に移動することです。

于 2013-03-02T00:18:39.430 に答える
0

これがパフォーマンスにとって本当に不可欠な場合は、いつでもデータモデルを少し非正規化できると思います。ストーリー オブジェクトに owner_person_uid 属性のコピーを追加できます。そうすれば、述語はそれほど多くの関係をトラバースする必要がなくなります。

このソリューションでは、プロパティの 1 つを変更した場合、関連するオブジェクトを常に更新する必要があります。

于 2013-03-02T00:31:48.700 に答える