Hive: その概要、NoSQLストレージ、ネイティブコード不要の開発

著者: IT Sectr 公開日: 2026-03-13 読了時間: 9 分

Hiveは、ネイティブコードなしで動作するFlutter向けの軽量NoSQLストレージです。SQLiteやFirebaseとは異なり、Hiveはネイティブライブラリを必要とせず、Dartのみで動作します。Pub.dev(2024年)によると、Hiveは1000万回以上ダウンロードされ、サーバーインフラなしでローカルデータストレージが必要なFlutterプロジェクトの3つに1つで使用されています。

主要ポイント

  • Hive — 純粋なDartによるNoSQL DB、ネイティブコードやプラットフォーム依存なし
  • パフォーマンス — モバイルデバイスで毎秒最大30,000回の読み取り
  • 型付け — カスタムオブジェクト向けTypeAdapter、コード生成不要
  • 軽量 — Android SDKやiOS UIKitへの依存ゼロ
  • リアクティブ — WatchBoxでリアルタイム変更追跡

Hiveとは?

Hiveは、完全にDartで書かれたNoSQLデータベースで、ネイティブライブラリを必要としません。2019年にSimon LeiterによってFlutterプロジェクト向けのSQLiteの代替として作成されました。Hiveはモバイルデバイスでの高速な読み書きに最適化されたバイナリ.hive形式でデータを保存します。.hive形式は、各データ型に独自のバイトプレフィックスを持つカスタムシリアライゼーションスキームを使用しており、Protocol BuffersやFlatBuffersとは異なり、事前のスキーマ知識なしでファイルを読み取ることができます。

Hiveの核となるアイデアは最大限のシンプルさです。データベースはネイティブエンジンの初期化を必要とせず、SQLパーサーを含まず、リフレクションも使用しません。すべての操作は、WriteBufferReadBufferによるバイナリシリアライゼーションを伴う直接のDart関数呼び出しです。

Flutter Communityの調査(2023年)によると、HiveはFlutterで最も使用されているデータストレージパッケージのトップ5に入り、人気ではshared_preferencesに次ぐ第2位ですが、機能性と速度ではそれを上回っています。

Hiveのアーキテクチャ

HiveはBoxの概念を使用します — これはリレーショナルデータベースのテーブルに類似しています。各Boxは、キーと値のペアのセットを含むディスク上のファイルです。キーはintまたはString、値は任意のプリミティブ型、リスト、Map、またはTypeAdapterを介したカスタムオブジェクトにできます。Boxは互いに分離されており、独立して開かれます。

ネイティブソリューションに対する利点

Hiveはプラットフォームチャネルを必要としません。つまり、追加設定なしでAndroid、iOS、Web、macOS、Windows、Linuxで同じように動作します。Webビルドを対象とするプロジェクトでは、Hiveが唯一の軽量NoSQLソリューションです — SQLiteはブラウザでは動作しません。HiveはWebのバックエンドとしてIndexedDBを使用し、ブラウザ環境でもデータの永続性を保証します。

Hiveの仕組み

Hiveは書き込み時にデータをバイナリ形式にシリアライズし、読み取り時にデシリアライズします。内部メカニズムはBinaryWriterBinaryReaderに基づいており、データをコンパクトなバイト配列にパッケージ化します。ディスク上のストレージサイズは、同じデータのJSON表現よりも平均して2~3倍小さくなります。

Boxを開くとき、Hiveはファイル全体をRAMにロードします。これにより高速な読み取り(マイクロ秒)が実現しますが、サイズ制限が課されます:1 Boxあたり50~100 MBを超えて保存しないことを推奨します。より大きなボリュームの場合は、LazyBox(ディスクからのレコードの遅延ロード)を使用してください。

トランザクションと並行性

HiveはDartアイソレート内でシングルスレッドで動作します。書き込み操作はファイルロックを伴う同期的に実行されます。非同期アクセスには、await付きのHive.openBox()を使用してください。複数のアイソレートからの同時アクセスは直接サポートされていません — 別の同期メカニズムが必要です。

Hive vs SharedPreferences vs SQLite

HiveはSharedPreferencesとSQLiteの間のニッチを占めています。SharedPreferencesよりも複雑(カスタムオブジェクトをサポート)ですが、SQLiteよりもシンプル(SQLクエリ不要)です。主な特徴を比較してみましょう。

特徴HiveSharedPreferencesSQLite
データ型任意(TypeAdapter経由)プリミティブのみSQL型
読み取り速度~30,000 ops/s~5,000 ops/s~2,000 ops/s
ネイティブコード不要必要(Android)必要
Web対応ありなしなし
複雑さ低い最小限中程度
リアクティビティWatchBoxなしORM経由

Hiveを選ぶべき場合

Hiveは少量のデータに最適です:アプリ設定、APIレスポンスのキャッシュ、ローカル同期キュー、お気に入り、閲覧履歴。データが50 MBを超えず、リレーショナルクエリを必要としない場合、HiveはSQLiteよりも高速でシンプルです。

Hiveが適さない場合

Hiveは複数フィールドによるフィルタリング、JOIN、集計関数を含むクエリをサポートしていません。「今日の優先度3以上のタスクをすべて選択」のような複雑なクエリが必要な場合は、driftやfloorと一緒にSQLiteを使用してください。Hiveはメモリにロードされるため、100 MBを超えるデータの保存にも適していません。

Hiveのコード例

Hiveは初期化とBoxのオープンから始まります。以下は典型的なシナリオ(Flutterアプリケーションでのタスクリストの保存)の基本操作です。すべての例はネイティブプラットフォーム呼び出しなしで動作します。

初期化とBoxのオープン

Hiveを使用する前に、main関数でHive.initFlutter()を呼び出す必要があります。その後、Hive.openBox()を介してBoxを開きます — 結果は読み取りと書き込みの準備ができたBoxインスタンスになります。

dart
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';

void async main() {
    await Hive.initFlutter();
    final settingsBox = await Hive.openBox('settings');
    runApp(MyApp());
}

CRUD操作

Boxはput、get、deleteメソッドと、すべてのエントリを走査するイテレータを提供します。キーと値はジェネリックスを介して型付けされます — デフォルトではBox<dynamic>は任意の型を受け入れますが、具体的な型を指定することを推奨します。

dart
// データの書き込み
final box = await Hive.openBox<String>('tasks');
await box.put('task_1', '食料品を買う');

// 読み取り
final task = box.get('task_1');

// すべてのキー
final allTasks = box.values.toList();

// 削除
await box.delete('task_1');

// Boxをクリア
await box.clear();

WatchBoxによるリアクティブ監視

WatchBoxはBoxの拡張で、変更をサブスクライバーに通知します。Flutterでは、ValueListenableBuilderと統合されます:Box内の値が変更されると、setStateを呼び出さずにウィジェットが自動的に再構築されます。

dart
final watchBox = await Hive.openBox('settings');

// ウィジェット内
ValueListenableBuilder(
    valueListenable: watchBox.listenable(),
    builder: (context, box, _) {
        final counter = box.get('counter') ?? 0;
        return Text('カウンター: $counter');
    },
)

TypeAdapterとカスタムオブジェクト

TypeAdapterは、カスタムDartオブジェクトをシリアライズするためのHiveのメカニズムです。アダプターは、オブジェクトをバイナリ形式に変換する方法(write)と元に戻す方法(read)を記述します。json_serializableとは異なり、TypeAdapterはリフレクションを必要とせず、より高速です。

TypeAdapterの作成

アダプターはTypeAdapterインターフェースをreadとwriteの2つのメソッドで実装します。クラスはBoxを開く前にHive.registerAdapter()を介して登録されます。各アダプターには数値IDが割り当てられ、型識別のためにファイルに保存されます。

dart
// データモデル
class Task {
    final String title;
    final bool isCompleted;
    Task({required this.title, this.isCompleted = false});
}

// TypeAdapter
class TaskAdapter extends TypeAdapter<Task> {
    @override
    final int typeId = 0;

    @override
    Task read(BinaryReader reader) {
        return Task(
            title: reader.readString(),
            isCompleted: reader.readBool(),
        );
    }

    @override
    void write(BinaryWriter writer, Task obj) {
        writer.writeString(obj.title);
        writer.writeBool(obj.isCompleted);
    }
}

コード生成によるアダプターの生成

多数のモデルがあるプロジェクトの場合、Hiveはhive_generatorbuild_runnerを提供します。クラスに@HiveTypeアノテーション、フィールドに@HiveFieldを付けると、アダプターが自動的に生成されます。これはモデルに10+のフィールドがある場合に便利です — 手動でのread/writeの記述は面倒になります。

Hiveのパフォーマンス最適化

Hiveはディスクではなくメモリから読み取り、毎秒最大30,000操作の速度を提供します。最適化のため:Boxを一度開いてアプリ全体で再利用し、openBoxを繰り返し呼び出さないでください。初期化後はHive.box()(同期的ゲッター)を使用してください — 新しいインスタンスを作成せずに既に開かれているBoxを返します。

ProviderおよびRiverpodとのHive連携

Hiveは人気のあるFlutter状態管理と簡単に統合できます。Providerの場合は、初期化時にBoxからデータを読み取り、listenableを介して更新するChangeNotifierProviderを使用します。Riverpodの場合は、WatchBoxにサブスクライブしたStreamProviderが適しています。この組み合わせにより、手動のsetState呼び出しなしで、Hiveのデータ変更ごとにリアクティブなUI更新が提供されます。典型的なFlutterプロジェクトでは、このアーキテクチャによりグローバルシングルトンなしで画面間の状態同期が可能になります。

よくある質問

HiveはFlutterなしで使用できますか?

Hiveは純粋なDartで動作するため、サーバーサイド(Dart VM)、コンソール、AngularDartなど、任意のDartプロジェクトで使用できます。Flutterの場合は、ストレージパスの初期化のために追加でhive_flutterが必要です。

Hiveでデータを暗号化するには?

HiveはBoxを開く際のencryptionKeyパラメータを通じてAES-256暗号化をサポートしています。キーは32バイトの文字列である必要があります。暗号化されたBoxはキーなしでは読み取れません — データはファイルレベルで保護されています。

HiveとIsarの違いは?

Isarは同じ作者(Simon Leiter)によるHiveの後継です。Isarはより高速で、インデックス、リレーションシップ、複雑なクエリをサポートしています。ただし、HiveはIsarのリレーショナル機能が必要ないシンプルなシナリオや、最小限の依存関係が重要なプロジェクトで今も有用です。

Hiveはスキーママイグレーションをサポートしていますか?

Hiveには組み込みのマイグレーションはありません。TypeAdapterの構造が変更された場合、古いデータはデシリアライズされません。解決策:アダプターのtypeIdを増やしてコードで手動マイグレーションを記述するか、新しいキーを書き込む前に古いキーにdeleteを使用します。

Hive Boxの最大サイズは?

HiveはBox全体をメモリにロードします。推奨制限は1 Boxあたり50~100 MBです。これを超えると、Boxを開く際の遅延やRAM消費の増加が発生する可能性があります。より大きなボリュームの場合は、複数のBoxまたは遅延ロード付きのLazyBoxを使用してください。

まとめ

  • Hive — 純粋なDartによるNoSQL DB、ネイティブコードやプラットフォーム依存なし
  • パフォーマンス — モバイルデバイスで毎秒最大30,000回の読み取り操作
  • TypeAdapter — リフレクションなしのカスタムオブジェクトのバイナリシリアライゼーション
  • WatchBox — 自動UI更新のためのリアクティブな変更追跡
  • クロスプラットフォーム — Android、iOS、Web、macOS、Windows、Linuxが標準対応
  • 暗号化 — BoxファイルレベルでのAES-256データ保護
  • 推奨 — FlutterおよびDartプロジェクトでのキャッシュ、設定、少量データにHiveを使用

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください