Realm ファイル サイズの縮小 - Swift SDK
項目一覧
Overview
Realm ファイルのサイズは、その中に保存されているオブジェクトの合計サイズよりも常に大きくなります。 このアーキテクチャにより、Realm の優れたパフォーマンス、同時実行性、および安全性の利点の一部が可能になります。
Realm は、ファイル内で追跡される未使用のスペース内に新しいデータを書込みます。 状況によっては、未使用の領域が Realm ファイルの大部分を構成することがあります。 Realm のデフォルトの動作は、Realm ファイルが大きくなりすぎるのを防ぐために、ファイルを自動的に圧縮することです。 自動圧縮がユースケースに十分でない場合、または自動圧縮のないバージョンの SDKを使用している場合は、 手動圧縮 戦略を使用できます。
Realm ファイルのサイズ
一般的に、Realm ファイルは同等の SQLite データベースよりもディスク上で必要なスペースが少なくなります。 予期しないファイル増加は、Atlas App Services が古いデータを参照していることと関連している可能性があります。 これらの要因はファイル サイズに影響を与える可能性があります。
トランザクションの固定
スレッド化
ディスパッチ キュー
圧縮してファイル サイズを縮小する場合には、次のように注意する必要があることがいくつかあります。
圧縮は、リソースを集中的に消費する操作になる可能性があります
圧縮により UI スレッドがブロックされる可能性があります
これらの要因により、Realm を開くたびにRealm を圧縮することは避けて、代わりにRealm を圧縮するときにを考慮する必要があります。 これは、アプリケーションのプラットフォームと使用パターンによって異なります。 圧縮するタイミングを決定する際には、 iOS ファイル サイズの制限を考慮してください。
ピン留めトランザクションを避ける
Realm は、読み取りトランザクションの有効期間を Realm インスタンスのメモリ有効期間に関連付けます。 古い Realm トランザクションを「ピン留めする」のを避けます。 自動更新 Realm を使用し、明示的な自動リリース プールでバックグラウンド スレッドからの Realm API の使用をラップします。
スレッド化
Realm は、実行ループの反復開始時にアクセスするデータのバージョンを更新します。 これによりデータの一貫したビューが提供されますが、ファイル サイズに影響があります。
次のシナリオを考えてみましょう。
スレッド A : Realm からいくつかのデータを読み取り、長時間実行される操作のスレッドをブロックします。
スレッド B : 別のスレッドにデータを書き込みます。
スレッド A : 読み取りスレッドのバージョンは更新されません。 Realm は中間バージョンのデータを保持する必要があり、書込みごとにファイル サイズが増加します。
この問題を回避するには、Realm でvalidate()を呼び出します。 これは、これまで読み取ったオブジェクトが不要になることをRealm に伝えています。 これにより、Realm はそれらのオブジェクトの中間バージョンを追跡することが解放されます。 次回アクセスすると、Realm には最新バージョンのオブジェクトが含まれます。
Realm を圧縮するために、次の 2 つの方法を使用することもできます。
ディスパッチ キュー
Grid Central Dispatch を使用してRealmにアクセスする場合 では、同様のファイルが増加する可能性があります。ディスパッチ キューのオートリリース プールは、コードの実行後すぐにドレイン されない可能性があります。 Realmは、ディスパッチ プールが邦土オブジェクトを処理するまで、データの中間バージョンを再利用できません。ディスパッチ キューから邦土にアクセスする場合は、明示的な自動リリース プールを使用します。
自動圧縮
バージョン10.35.0の新機能。
SDK は、ファイル内のデータを継続的に再割り当てし、未使用のファイル領域を排除することで、Realm ファイルをバックグラウンドで自動的に圧縮します。 自動圧縮は、ほとんどのアプリケーションの Realm ファイル サイズを最小限に抑えるのに十分です。
自動圧縮は、ファイル内の未使用領域のサイズがファイル内のユーザー データのサイズの 2 倍を超えると開始されます。 自動圧縮は、ファイルがアクセスされていない場合にのみ行われます。
手動圧縮
手動圧縮は、ファイル サイズをより厳密に管理する必要があるアプリケーションや、自動圧縮をサポートしていない古いバージョンの SDK を使用するアプリケーションに使用できます。
Realm の手動圧縮は次の方法で機能します。
Realm ファイルの内容全体の読み取り
別の場所にある新しいファイルに内容を書込み (write)
元のファイルの置き換え
ファイルに多くのデータが含まれている場合、コストのかかる操作になる可能性があります。
Realm を圧縮するには、ShouldCompactOnLaunch() (Swift)またはShouldCompactOnLaunch (Objective-C)を使用します。 次のような、このメソッドを実行するための条件を指定します。
ディスク上のファイルのサイズ
ファイルに含まれる空き領域の量
メソッドで実行する条件の詳細については、「手動圧縮を使用するためのヒント 」を参照してください。
重要
圧縮が発生しない可能性があります
Realm がアクセスされている間は、構成設定に関係なく、圧縮は実行されません。
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; config.shouldCompactOnLaunch = ^BOOL(NSUInteger totalBytes, NSUInteger usedBytes) { // totalBytes refers to the size of the file on disk in bytes (data + free space) // usedBytes refers to the number of bytes used by data in the file // Compact if the file is over 100MB in size and less than 50% 'used' NSUInteger oneHundredMB = 100 * 1024 * 1024; return (totalBytes > oneHundredMB) && ((double)usedBytes / totalBytes) < 0.5; }; NSError *error = nil; // Realm is compacted on the first open if the configuration block conditions were met. RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error]; if (error) { // handle error compacting or opening Realm }
let config = Realm.Configuration(shouldCompactOnLaunch: { totalBytes, usedBytes in // totalBytes refers to the size of the file on disk in bytes (data + free space) // usedBytes refers to the number of bytes used by data in the file // Compact if the file is over 100MB in size and less than 50% 'used' let oneHundredMB = 100 * 1024 * 1024 return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5 }) do { // Realm is compacted on the first open if the configuration block conditions were met. let realm = try Realm(configuration: config) } catch { // handle error compacting or opening Realm }
Realm を非同期に圧縮
Swift async/await 構文を使用してRealmを非同期に開くと、バックグラウンドでRealmを圧縮できます。
func testAsyncCompact() async { let config = Realm.Configuration(shouldCompactOnLaunch: { totalBytes, usedBytes in // totalBytes refers to the size of the file on disk in bytes (data + free space) // usedBytes refers to the number of bytes used by data in the file // Compact if the file is over 100MB in size and less than 50% 'used' let oneHundredMB = 100 * 1024 * 1024 return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5 }) do { // Realm is compacted asynchronously on the first open if the // configuration block conditions were met. let realm = try await Realm(configuration: config) } catch { // handle error compacting or opening Realm } }
Realm Swift SDK バージョン 10.15.0 および 10.16.0 以降では、Realm API の多くが Swift async/await 構文をサポートしています。 プロジェクトは、次の要件を満たしている必要があります。
Swift SDK バージョン | Swift バージョン要件 | サポートされている OS |
---|---|---|
10.25.0 | Swift 5.6 | iOS 13.x |
10.15.0 または 10.16.0 | Swift 5.5 | iOS 15.x |
アプリが async/await
コンテキストで Realm にアクセスする場合は、スレッド関連のクラッシュを回避するためにコードを@MainActor
でマークします。
圧縮コピーの作成
Realm.writeCopy(toFile:encryptionKey:) を使用して、Realm の圧縮された(およびオプションで 暗号化された )コピーを別のファイルの場所に保存できます使用して複数のドキュメントを挿入できます。 宛先ファイルがすでに存在することはできません。
重要
書込みトランザクション内でこのメソッドを呼び出すのを避けます。 書込みトランザクション内で呼び出されると、このメソッドは最新のデータをコピーします。 これには、このメソッドを呼び出す前にトランザクション内で行ったコミットされていない変更が含まれます。
手動圧縮を使用する際のヒント
Realm を圧縮すると、UI スレッドがブロックされる可能性があり、コストのかかる操作になる可能性があります。 Realm を開くたびにアプリケーションが圧縮されないようにする必要があります。 代わりに、アプリケーションが圧縮を最適化して、ファイルサイズが大きくなりすぎるのを防ぐのに十分な頻度で圧縮を行います。 アプリケーションがリソースが制限された環境で実行されている場合、一定のファイルサイズに達したときや、ファイルサイズがパフォーマンスに悪影響を及ぼす場合は、圧縮する必要がある場合があります。
これらの推奨事項は、アプリケーションの手動圧縮を最適化するのに役立ちます。
最大ファイルサイズを、平均 Realm 状態サイズの倍数に設定します。 平均的な Realm 状態サイズが 10 MB の場合は、予想される使用量とデバイスの制約に応じて、最大ファイル サイズを 20 MB または 40 MB に設定できます。
開始点として、Realm ファイルサイズの 50% 以上が使用されなくなった場合に Realm を圧縮します。 現在使用されているバイトを合計ファイルサイズで割った値で、現在使用されているスペースの割合を判断します。 次に、それが 50% 未満であるかどうかを確認します。 つまり、Realm ファイル サイズの 50% 以上が未使用領域であり、圧縮に適しています。 試すと、アプリケーションに最適なパーセンテージが異なることが見つかる場合があります。
これらの計算は、 shouldCompactOnLaunch
コールバックでは次のようになります。
// Set a maxFileSize equal to 20MB in bytes let maxFileSize = 20 * 1024 * 1024 // Check for the realm file size to be greater than the max file size, // and the amount of bytes currently used to be less than 50% of the // total realm file size return (realmFileSizeInBytes > maxFileSize) && (Double(usedBytes) / Double(realmFileSizeInBytes)) < 0.5
アプリケーション内の Realm ファイルを圧縮する頻度の適切なバランスを見つけるために、条件を試してください。
iOS ファイルのサイズ制限を考慮する
Realm ファイルが大きいと、アプリのパフォーマンスと信頼性に影響を与える可能性があります。 アプリケーションが iOS でマッピングできるメモリの量よりも大きくすることはできません。 この制限は、デバイスと、その時点でメモリ領域がどの程度フラグメント化されているかによって異なります。
より多くのデータを保存する必要がある場合は、複数の Realm ファイルにマッピングします。
概要
Realm のアーキテクチャではスレッド関連の利点が得られますが、ファイル サイズが増加する可能性があります。
自動圧縮により、ファイルにアクセスしていないときにファイル サイズの増加を管理できます。
自動圧縮がアプリケーションのニーズを満たせない場合は、
shouldCompactOnLaunch()
のような手動圧縮戦略を使用できます。別のプロセスが Realm にアクセスしている場合は、圧縮は実行されません。
async/await 構文を使用すると、バックグラウンドで Realm を圧縮できます。