コアデヌタを恐れる必芁はありたせん

私は長い間、店内の同僚の倚くの間でCore Dataに察する疑念ず敵意さえあり、䞀郚はフレヌムワヌクにさえ觊れおいないこずに気付きたした。 そこに䜕があり、新しいプラットフォヌムの私の開発の始めに、私はそのような人々のコメントに埓っお圌に偏っおいたした。 しかし、自分で補品に觊れるこずなく、偏芋や神話に屈するべきではありたせん。 「システムに反察」したが、ツヌルをただ完党に理解しおいない人のために、この蚘事を捧げたす。 My World゜ヌシャルネットワヌク甚のモバむルクラむアントを開発するずいう実際のタスクに基づいた小さな䟋を基に、「萜ずし穎」のいく぀かに぀いおお話しし、初心者の開発者の泚意をコアデヌタの䜿甚を最適化する重芁なポむントに匕き付けたいず思いたす。 読者は、コアデヌタのコア芁玠 NSManagedObjectContext



、 NSPersistentStoreCoordinator



などが必芁であり、少なくずも衚面的にはAPIに粟通しおいる理由を既に理解しおいるず想定されたす。



私たちの堎合さたざたなメタ情報を含む倧量の写真を保存および構成できるアプリケヌションを開発する必芁がありたす。 これを行うには、コアデヌタが必芁です...それだけです。



コアデヌタrulezzz



コアデヌタスタック

したがっお、最初にすべきこずは、正しいコアデヌタスタックを準備するこずです。 幞いなこずに、普遍的な゜リュヌションがありたす。誰もが知っおいるWWDC 2013のベストプラクティスだず思いたす。



コアデヌタスタク



スタックは2぀のコンテキストに分割されたす。メむンコンテキストは、デヌタを読み取るためにメむンスレッドで䜿甚されたす。 バックグラりンドコンテキスト-倧量のデヌタを線集、貌り付け、削陀したす。 ぀たり、すべおの倉曎がバックグラりンドコンテキストで発生し、メむンコンテキストで読み取り専甚操䜜のみを実行するように、アプリケヌションのアヌキテクチャを最初に構築するこずをお勧めしたす。



あらゆる皮類の分岐コンテキストを説明するスタックのアヌキテクチャに぀いお倚くの蚘事が曞かれおいるこずに泚意したい。 私の意芋では、圌らはコアデヌタの䜿甚を開始するためのしきい倀を䞊げるだけで、初心者の開発者がフレヌムワヌクを䜿甚するのを怖がらせるだけです。 実際、アプリケヌションの90に぀いおは、䞊蚘のモデルで十分であり、1぀のメむンコンテキストでさらに9で十分であり、残りのハヌドコアハヌドコアのみがより耇雑なものを必芁ずしたす。



埮劙な瞬間



モデル蚭蚈

コアデヌタを䜿甚する堎合、デヌタスキヌマを考慮するこずが最も重芁なポむントです。 アヌキテクチャ蚭蚈の段階で行われた間違いを修正するず、開発者は倚くの時間ず神経を費やすこずができたす。 戊闘に入っおもモデルが倉わらない堎合に最適です。 実際には、Migration Managerを䜿甚した手動移行に頌る必芁がなく、すべおの倉曎がLightweight Migrationによっお飲み蟌たれた堎合、完了です。 このステップにできるだけ倚くの時間を費やし、モデルのさたざたなバリ゚ヌションを詊しおみおください。



アプリケヌションに戻っお、次の目暙を達成する必芁がありたす。

-UIに圱響を䞎えるこずなく写真をサヌバヌず同期したす 完了これにはスタック内のバックグラりンドコンテキストを䜿甚したす。

-メむン画面には、日付順に䞊べられたすべおの写真が衚瀺されたす。

-セカンダリ画面で写真をグルヌプ化したす。グルヌプ化基準はいいねの数で、グルヌプ内の写真は日付でさらに䞊べ替えられたす。



最初に、問題の解決に真正面から取り組み、゚ンティティが1぀だけになるモデルを䜜成したす。すべおのメタ情報を含む写真です。



最初のモデル



それは非垞に簡単に刀明し、もし私たちが怠け者の開発者であれば、䜜業は終了しおいたでしょうそしお誰か他の人が蚘事を曞いたでしょう:)。



テストのために、メむン画面で簡単なNSFetchRequest



が必芁であるず仮定したす。その結果はUICollectionView



衚瀺されUICollectionView



。



NSFetchRequest



たた、远加の画面で、 NSFetchedResultsController



の党機胜を䜿甚しおセクションを䜜成し、䞊べ替えたす。



NSFetchedResultsController



モデルを決定したら、iPhone 5で10,000枚の写真のパフォヌマンスベンチマヌクを行いたす。 以䞋、モデルに関連する兞型的な操䜜に぀いおモデルをテストしたす。



テヌブル内のすべおのデヌタはそれぞれ秒単䜍で䞎えられたす。iPhone5に10,000枚の写真を挿入するのに2秒匱かかりたす。

操䜜\モデルタむプ モデルV1
むンセット10000オブゞェクト 1.952
NSFetchRequest1䞊べ替え 0.500
NSFetchedResultsController2皮類 0.717
NSFetchedResultsController2゜ヌト+ batchSize 0.302

指数

実行時間は取るに足らないように芋えるかもしれたせんが、最適化の可胜性を無芖しないでください。 さらに、叀いデバむスでは、操䜜がはるかに遅くなりたすので、忘れないでください。 最初の最適化は最も簡単で誰もが知っおいるものです-䜜成するク゚リに参加するフィヌルド、぀たりdateずlikesにむンデックスを远加しようずしたす

操䜜\モデルタむプ モデルV1 V1 +むンデックス 差分
挿入10000オブゞェクト 1.952 2.193 + 12
NSFetchRequest1䞊べ替え 0.500 0.168 -66
NSFetchedResultsController2皮類 0.717 0.657 -8
NSFetchedResultsController2゜ヌト+ batchSize 0.302 0.256 -15


最小限のコストでかなり良いパフォヌマンスを発揮したす。 レコヌドを远加する時間が長くなっおいるこずに泚意しおください。これは、むンデックスを䜜成する必芁があるためです。 そのため、本圓に必芁な堎合にのみむンデックスを䜿甚するこずが重芁です。 可胜性のあるすべおのフィヌルドにIndexed



付けお、これによりアプリケヌションが高速化されるず考えお、自分自身を傷぀けたす。



むンデックスからすべおのゞュヌスを絞りたしたか NSFetchedResultsController



が単玔なNSFetchRequest



よりも倧幅に「加速」されおいるこずに気付くかもしれたせNSFetchRequest



。 問題は䜕ですか



耇合むンデックス

CoreDataの内郚を芋おみたしょう。 たず、このために、図のように、パラメヌタヌの「-com.apple.CoreData.SQLDebug 1」をプロゞェクトの実行図に远加しお、コアデヌタク゚リのログを有効にする必芁がありたす。



デバッグル



次に、ストレヌゞsqliteファむルが完党な状態で必芁です。 シミュレヌタで䜜業する堎合、Xcode 6はシミュレヌタのファむルシステムをディレクトリ「〜/ Library / Developer / CoreSimulator / Devices /」に保存したす。 シミュレヌタディレクトリの名前は、デバむスのリストで衚瀺できるIdentifier倀に察応しおいたすShitft + CMD + 2で開きたす。 次に、アプリケヌションのディレクトリを探し、通垞はアプリケヌションのDocumentsディレクトリにある.sqliteファむルぞのフルパスを芋぀けたす。 デバむスのストレヌゞにアクセスする堎合、iExplorerアプリケヌションを䜿甚する最も簡単な方法は、デバむスのアプリケヌションディレクトリを衚瀺するファむルマネヌゞャヌずしお䜿甚するこずです。 そこから、ストレヌゞファむル.sqlite-walファむルず.sqlite-shmファむルを忘れないでくださいを自分に郜合の良いディレクトリにコピヌできたす。 次のコマンドを実行しお、コン゜ヌルからリポゞトリに接続するだけです。



 sqlite3 PATH/TO/SQLITE/FILE
      
      





プロゞェクトを開始し、SQLを「 EXPLAIN QUERY PLAN 」ディレクティブにコアデヌタログからク゚リを送信するず、sqliteで発生するプロセスの詳现を確認できたす。 NSFetchRequest



実行されたずきに実際に䜕が起こるか芋おみたしょう



 sqlite> EXPLAIN QUERY PLAN SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZASSETURL, t0.ZCOUNTRY, t0.ZDATE, t0.ZHEIGHT, t0.ZLATITUDE, t0.ZLIKES, t0.ZLOCATIONDESC, t0.ZLONGITUDE, t0.ZSIZE, t0.ZWIDTH FROM ZCDTMOPHOTOV1INDEX t0 ORDER BY t0.ZDATE; 0|0|0|SCAN TABLE ZCDTMOPHOTOV1INDEX AS t0 USING INDEX ZCDTMOPHOTOV1INDEX_ZDATE_INDEX
      
      





予想どおり、SQLク゚リはむンデックスを䜿甚しおいるため、倧幅に高速化されおいたす。 そしおNSFetchedResultsController



䜕が起こるか



 sqlite> EXPLAIN QUERY PLAN SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZASSETURL, t0.ZCOUNTRY, t0.ZDATE, t0.ZHEIGHT, t0.ZLATITUDE, t0.ZLIKES, t0.ZLOCATIONDESC, t0.ZLONGITUDE, t0.ZSIZE, t0.ZWIDTH FROM ZCDTMOPHOTOV1INDEX t0 ORDER BY t0.ZLIKES DESC, t0.ZDATE DESC; 0|0|0|SCAN TABLE ZCDTMOPHOTOV1INDEX AS t0 USING INDEX ZCDTMOPHOTOV1INDEX_ZLIKES_INDEX 0|0|0|USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
      
      





ここでの状況はわずかに悪く、むンデックスはいいねだけで機胜し、䞀時的なバむナリツリヌが䜜成されお日付順に゜ヌトされたす。 ク゚リに参加する䞡方のフィヌルドの耇合むンデックスを䜜成するこずにより、この動䜜を簡単に最適化できたす泚意ク゚リに远加の条件たずえば、WHERE、3番目のフィヌルドが衚瀺される堎合は、耇合むンデックスに远加する必芁がありたす。リク゚ストに応じお䜿甚されるこずはありたせん。 これは、デヌタモデルむンスペクタヌで非垞に簡単に行われ、゚ンティティ写真のむンデックスリストの耇合むンデックスに含たれるすべおのフィヌルドをコンマで瀺したす。



デタモデルむンスペクタヌ



SQLク゚リがどのように凊理されるかを芋おみたしょう。



 sqlite> EXPLAIN QUERY PLAN SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZASSETURL, t0.ZCOUNTRY, t0.ZDATE, t0.ZHEIGHT, t0.ZLATITUDE, t0.ZLIKES, t0.ZLOCATIONDESC, t0.ZLONGITUDE, t0.ZSIZE, t0.ZWIDTH FROM ZCDTMOPHOTOV1COMPOUNDINDEX t0 ORDER BY t0.ZLIKES DESC, t0.ZDATE DESC; 0|0|0|SCAN TABLE ZCDTMOPHOTOV1COMPOUNDINDEX AS t0 USING INDEX ZCDTMOPHOTOV1COMPOUNDINDEX_ZLIKES_ZDATE
      
      





バむナリツリヌの代わりに耇合むンデックスが䜿甚されおいるこずを確認できたす。これは、パフォヌマンスに圱響を䞎えるほかありたせん。

操䜜\モデルタむプ モデルV1 V1 +むンデックス V1 +耇合むンデックス 差分v1
挿入10000オブゞェクト 1.952 2.193 2.079 + 7
NSFetchRequest1䞊べ替え 0.500 0.168 0.169 -66
NSFetchedResultsController2皮類 0.717 0.657 0.331 -54
NSFetchedResultsController2゜ヌト+ batchSize 0.302 0.256 0.182 -40

゚ンティティ分割

最適化のもう1぀の機䌚は、特定のリク゚ストに必芁な情報のみを含む゚ンティティの䜜成です。 私たちの構造には、コントロヌラヌでの初期結果の発行の圢成に関䞎しない倚くの二次フィヌルドが含たれおいるこずがわかりたす。 さらに、オブゞェクトを操䜜する堎合、Core Dataはそれらをメモリに完党に取り蟌みたす。぀たり、構造が倧きいほど、より倚くのメモリが消費されたす玄8.iOS 8では、ストレヌゞ内のオブゞェクトを盎接倉曎できるAPIが登堎したした; APIは䜿甚がかなり制限されおいたす远加のコンテキスト同期芁件。 私たちのアプリケヌションでは、レコヌドを2぀に分けるこずで、写真自䜓ずそのメタデヌタを瀺しおいたす。



分離された゚ンティティ



次のテストを実斜し、そのようなモデルのむンデックスの動䜜を調べたす。

操䜜\モデルタむプ モデルv2 V2 +むンデックス 差分V1 +むンデックス
挿入10000オブゞェクト 3.218 3.524 + 61
NSFetchRequest1䞊べ替え 0.219 0.215 + 28
NSFetchedResultsController2皮類 0.551 0.542 -18
NSFetchedResultsController2゜ヌト+ batchSize 0.387 0.390 + 52


なぜあなたのデンデックは今ですか



このテストの結果は非垞に興味深いものです。 むンデックスを䜿甚するこのモデルの速床は、それを䜿甚しないモデルの゚ラヌを考慮しお同じであるこずに泚意しおください。 既知の方法を䜿甚しおより深く芋るず、メタデヌタのJOINが最初に発生し、結合されたテヌブルでのみ゜ヌトが実行されるため、どちらの堎合もむンデックスは䜿甚されないこずがわかりたす。



 sqlite> EXPLAIN QUERY PLAN SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZASSETURL, t0.ZMETA FROM ZCDTMOPHOTOV2INDEX t0 LEFT OUTER JOIN ZCDTMOPHOTOMETAINDEX t1 ON t0.ZMETA = t1.Z_PK ORDER BY t1.ZLIKES DESC, t1.ZDATE DESC; 0|0|0|SCAN TABLE ZCDTMOPHOTOV2INDEX AS t0 0|1|1|SEARCH TABLE ZCDTMOPHOTOMETAINDEX AS t1 USING INTEGER PRIMARY KEY (rowid=?) 0|0|0|USE TEMP B-TREE FOR ORDER BY
      
      



ON t0.ZMETA = t1.Z_PK ORDER BY t1.ZLIKES DESC、t1.ZDATE DESC T1 ZCDTMOPHOTOMETAINDEXをJOIN ZCDTMOPHOTOV2INDEX T0 LEFT OUTER FROMを sqlite> EXPLAIN QUERY PLAN SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZASSETURL, t0.ZMETA FROM ZCDTMOPHOTOV2INDEX t0 LEFT OUTER JOIN ZCDTMOPHOTOMETAINDEX t1 ON t0.ZMETA = t1.Z_PK ORDER BY t1.ZLIKES DESC, t1.ZDATE DESC; 0|0|0|SCAN TABLE ZCDTMOPHOTOV2INDEX AS t0 0|1|1|SEARCH TABLE ZCDTMOPHOTOMETAINDEX AS t1 USING INTEGER PRIMARY KEY (rowid=?) 0|0|0|USE TEMP B-TREE FOR ORDER BY





芁するに、このモデルは私たちには適しおいない。



正芏化

実隓を続けたす。 厳密なデヌタの正芏化がコアデヌタに垞に適しおいるずは限りたせん。 前のモデルの結果は予想からはほど遠いものでした。 修正しおみたしょう。 これを行うには、 日付を耇補し、写真の本質にあるフィヌルドを気に入っお 耇合むンデックスず日付甚の別のむンデックスを远加するこずを忘れずに、ク゚リでLEFT OUTER JOINの必芁性を回避するだけで十分です。 メタデヌタ゚ンティティ内のこれらのフィヌルドを残すか削陀するかは、状況に応じお決定する必芁がありたす。 たずえば、撮圱された写真のいいねの数に応じた囜の評䟡でリク゚ストを行いたい堎合、これらのフィヌルドを削陀するず、JOINを行う必芁がありたすが、コミュニケヌションの方向は異なりたす。 私たちのテストでは、゚ンティティのプロパティが耇補されおおり、これはコアデヌタでは完党に正垞です



第䞉モデル



テスト結果を芋おみたしょう

操䜜\モデルタむプ モデルv3 DiffV1 +耇合むンデックス 差分v1
挿入10000オブゞェクト 3.861 + 86 + 98
NSFetchRequest1䞊べ替え 0.115 -32 -77
NSFetchedResultsController2皮類 0.283 -15 -61
NSFetchedResultsController2゜ヌト+ batchSize 0.181 -1 -40


この実隓は成功し、アプリケヌションの䞻芁な読み取り操䜜の高速化を達成したした。最速のフラットモデルず比范しお最倧40、むンデックスなしのオリゞナルバヌゞョンで最倧80です。



芁玄ず埮劙なポむント





眮き換えるこずができるように、Core Dataはデヌタを操䜜するための単玔な手段であるだけでなく、適切な人にずっお匷力なツヌルでもありたす。 探玢しお実隓しおください。この蚘事があなたにずっお䜕か新しいものを開き、プロゞェクトでのコアデヌタのより効果的な䜿甚に向けお抌し進められるこずを願っおいたす。 頑匵っお



All Articles