2016-09-22 5 views
1

私は現在プロジェクトにcoredataを使用しています。しかし、アプリケーションが更新する必要がある54000個のオブジェクトをAPIが返すと、ユーザーはほぼ2時間待たなければなりません。 これは現在のプロジェクトにとって大きな問題です。私はsqliteを使用し、coredataを使わずに何千ものオブジェクトを更新することを考えています。Sqliteまたはコアデータより多くの50000レコードを更新する

Sqliteを使用するのは正しい判断ですか、それともCoreDataの提案ですか?私は決めることができません。どんな助けも素晴らしいでしょう。ありがとうございました。ここで

は私がやっているものです:

NSManagedObjectContext *privateObjectContext = [AppDelegate appDelegate].privateManagedObjectContext; 
    [privateObjectContext performBlock:^{ 

     int i = 1; 
     for (NSDictionary *item in itemlist) { 
      i++; 

      [fetchRequest setPredicate:[NSPredicate predicateWithFormat: 
             @"itemID == %@",[item objectForKey:@"item_id"] 
             ]]; 
      NSError *error; 
      NSMutableArray *inventories = [[NSMutableArray alloc]initWithArray: 
              [privateObjectContext executeFetchRequest:fetchRequest 
                       error:&error]]; 
      ItemManagedObject *itemMO; 

      if(inventories.count){ 
       itemMO = inventories.firstObject; 
      }else{ 
       itemMO = [NSEntityDescription insertNewObjectForEntityForName:@"ItemObject" 
                 inManagedObjectContext:privateObjectContext]; 
      } 
      [itemMO prepareWithDictionary:item]; 
     } 

     NSError *error; 
     if (![privateObjectContext save:&error]) { 
      completionHandler(NO); 
     } 
} 
+0

オブジェクトを現在どのように更新しているかについて、2時間ほどかかりますか?それを改善する方法があるかもしれませんが、あなたが今何をしているのか分からないと言うことは不可能です。 –

+0

はい、私たちはもっと詳しく、どのように更新を処理していますか、コンテキストを保存する頻度、ボトルネックを探すために機器を使用したか、いくつかのコードを投稿してください – trapper

+0

@TomHarringtonコードを追加します。 – mega90

答えて

0

2時間は非常に長いです。それは変だ。

しかし、あなたのコードをマッサージするには、コアデータの使用が少なくて済みます。はるかに少ない仕事。

  1. 、プロパティの値がを変更しないとき、オブジェクトが不必要に汚れとしてフラグ付けされないように、管理対象オブジェクトのプロパティのセッターを呼び出さないでくださいリクエスト
  2. をフェッチ代わりに54Kの単一フェッチ要求を実行しますコアデータは、「保存」メソッドが呼び出されたときにオブジェクトの高価ではあるが役に立たない更新を実行する必要はありません。

これにより、Core Dataが実行する作業量とアプリケーションのパフォーマンスが大幅に低下します。

2番目の点は簡単ですが、非常に冗長です。セッターを呼び出す前に、個々のプロパティ値を辞書値と比較してください。

最初の点は、アルゴリズムの変更を必要とする:IDによって

ソート辞書([NSArrayのsortedArray ...]を有する:

は([NSFetchRequest setSortDescriptors]で)IDでソート単一のフェッチ要求を実行します)

2つのソートされたリスト(両方のリストがソートされていることを最優先事項である)を同期:

NSEnumerator *itemMOEnum = [itemMOs objectEnumerator]; 
NSEnumerator *dicEnum = [dictionaries objectEnumerator]; 
ItemManagedObject *itemMO = [itemMOEnum nextObject]; 
NSDictionary *itemDic = [dicEnum nextObject]; 

while (itemDic) { 
    NSComparisonResult comparison = itemMO ? [itemDic[@"item_id"] compare:itemMO.itemID] : NSOrderedAscending; 
    switch (comparison) { 
     case NSOrderedSame: 
      // id present in both lists: update 
      [itemMO prepareWithDictionary:itemDic]; 

      itemMO = [itemMOEnum nextObject]; 
      itemDic = [dicEnum nextObject]; 
      break; 

     case NSOrderedAscending: { 
      // id present only in dictionaries: create 
      itemMO = [NSEntityDescription insertNewObjectForEntityForName:@"ItemObject" 
              inManagedObjectContext:privateObjectContext]; 
      [itemMO prepareWithDictionary:itemDic]; 

      itemDic = [dicEnum nextObject]; 
     } break; 

     case NSOrderedDescending: 
      // id present only in managed object: delete or do nothing 
      itemMO = [itemMOEnum nextObject]; 
      break; 
    } 
} 

while (itemMO) { 
    // id present only in managed object: delete or do nothing 
    itemMO = [itemMOEnum nextObject]; 
} 

をして保存。

最後に、SQLiteの方が速いかもしれません(コアデータとSQLiteライブラリのパフォーマンスを比較する試みについては、https://github.com/groue/GRDB.swift/wiki/Performanceを参照してください)。

しかし、SQLiteは遅いアルゴリズムを高速のにしません。

+0

ありがとうございました。それは7分かかります。私はNSEnumeratorの使用を考えたことがありません。遅刻して申し訳ありません。 – mega90

0

を私はコアデータプロジェクトのsqliteまたはその逆をやり直したことがありません。性能差があるかどうかは分かりません/

しかし、54k = 2時間のものは非常に奇妙に聞こえます。あなたは私がサーバーが関与していると思わせるAPIについて話します。あなたの質問はデータベースに関するものです。確かに2時間は長すぎると思うので、データベースのコアデザインに問題があるかどうか疑問に思う。たとえば、索引がないなどです。クエリとデータベースによっては、1回の更新で多種多様な処理がトリガされる可能性があります。

もう1つの理由は、デバイス上でこのデータ列を処理している理由です。それは扱うことがたくさんありますし、音量を下げる方法、選択的に更新する方法、それとももっと良い方法をサーバーに移す方法があるのだろうかと思います。

私はあなたの質問を考え直す必要があると思います。データベースについてより多くのコンテキストを提供します。これは、正確に何をやっているのか、そしてその理由です。

+0

@jrturtonと同様に、「itemListに54,000個のオブジェクトが含まれている場合、永続ストアに54,000フェッチを実行して毎回1つのIDをチェックしています。 。私はcoredataのこの作業システムを知らなかった。私は2時間の答えはこれだと思います。 – mega90

0

CoreDataはデータベースマネージャではなく、オブジェクトグラフと永続マネージャです。 CoreDataは、オブジェクトをsqliteデータベースに格納するだけでなく、XMLファイルまたはバイナリファイルに格納することもできます(開発者は、ニーズに最適なオプションを選択します)。

CoreDataとデータベースマネージャの主な違いは、CoreDataを使用してオブジェクトにアクセスすると、CoreDataが目的のC/Swift対応オブジェクトをインスタンス化する必要があることです。

Sqliteは、データを含む完全なレコードを抽出することなく、データの一部にアクセスできます。

そして、CoreDataは、オブジェクト間の関係グラフ(2つのCoreDataクラス間の関係、そして一般に両方の方法で)を維持する必要があります。

したがって、54kオブジェクトを更新するときに、CoreDataに(メモリ内の)54kオブジェクトをインスタンス化し、最終的にそれらの関係を更新するように要求します。

これは、CoreData for mobileにとって非常に重労働です。

CoreDataモデルが正しく最適化されていない可能性があります。 CoreDataコンテキストを定期的に保存し、CoreDataスクラッチパッド(実際に読み込みまたは更新されたオブジェクトを含むメモリの一部)をフラッシュする必要があります。

私の経験では、CoreDataは大量のデータ作業には適していません。

sqliteでニーズを再実装することは、sqliteレコードからクラスオブジェクトを再インスタンス化し、かなりの自動関係を管理できるようにするためにはかなりの作業ですが、実行可能です。私はいくつかのプロジェクトでそれをやった。これは、sqliteが多くのプラットフォームで利用可能であるため、Androidなどの他のプラットフォームとより共有可能なモデルオブジェクトを持つという利点をもたらします。

さらにもう1つ:sqliteは複数のスレッドから使​​用する方が適しています。 CoreDataはこれにもっと敏感であり、スレッドによって1つのコンテキストが必要であり、最終的にはいくつかのコンテキスト同期が必要です。

+0

説明をありがとう、今私はコアデータとsqliteの違いを理解しています。時には質問をして問題を理解し、ウェブで検索してアイデアを得ようと思ったことをもっと知るためにもっと意見を聞くことが良い(私は検索しましたが、今はもっと良く理解しています) – mega90

1

コアデータにはNSBatchUpdateRequestが用意されています。これにより、管理対象オブジェクトをメモリにインスタンス化して処理することなく、永続ストアで直接更新を行うことができます。

コアデータパフォーマンス計測器を使用してこのコードを実行する必要があります。 itemListに54,000のオブジェクトが含まれている場合は、永続ストアに54,000フェッチを実行して毎回1つのIDをチェックします。すべてのIDを前面から取得し、メモリ内の結果を確認するのは、フェッチ要求を繰り返すよりもはるかに高速です。コードは、Core Dataの場合と同じように、生のSQLではほとんど遅くなります。

また、このコードは間違って見える:

ItemManagedObject *itemMO; 

if(itemMO.count){ 

テスト場合は、どこかにラインを逃していない限り、ということを渡すつもりはありませんです。

+0

ups.while私はstackoverflowに関する質問を編集していましたそれは間違って書いた。しかし、3つまたは4つの列はそれぞれ異なる値を持つことができます。それらのうちのどれも同じではありません。したがって、この状況ではNSBatchUpdateRequestは役に立たない。とにかく感謝します。答えでは、より良い説明とsqlite coredataの違いについてもっと学んだ。だから、私は構造体をcoredataからsqliteを使用するように変換するのが良いでしょう。 – mega90

関連する問題