[Android] Firebase Cloud Firestoreの一括書き込みをやってみた

NoSQLクラウドデータベースのFirestore(Android)で500件以上の一括書き込みを実装する機会があったので実装方法やパフォーマンスについて共有します。
2019.09.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは。Androidエンジニアの山本です。NoSQLクラウドデータベースのFirebase Firestore (Android)で500件以上の一括書き込みを実装する機会があったので実装方法やパフォーマンスについて共有します。

前提条件

Cloud Firestore データベースの作成と開発環境の設定が終わっていること。
Cloud Firestore を使ってみる

Firestoreの一括書き込み

Firestoreには、大量のデータを操作するのに適した「一括書き込み」があります。一括書き込みは、set(), update(), delete()のオペレーションが用意されていて、これらを最大500件組み合わせて実行することができます。以下は一括書き込みのset()で1000件のデータを書き込む例です。

// 1000件のサンプルデータ
val cityList: MutableList<City> = getSampleCityList()
val db = FirebaseFirestore.getInstance()

// 1. 一括書き込み開始
var batch: WriteBatch = db.batch()
cityList.forEachIndexed { index, city ->
    val ref: DocumentReference = db.collection("cities").document(city.name!!)
    batch.set(ref, city)
    if ((index + 1) % 500 == 0 || index == cityList.lastIndex) {

        // 2. オペレーションが500件に達したらコミット
        batch.commit().addOnCompleteListener {
            Log.d(TAG, "batch commit isSuccess: ${it.isSuccessful}")

        }
        // 3. 新たに一括書き込みを開始する
        batch = db.batch()
    }
}

一括書き込みを開始して、オペレーションが500件に達したらコミットしています。注意点としてコミット後にWriteBatchのインスタンスが使い回し出来ないため、新たに一括書き込みを開始する必要があります。サンプルデータ生成のプログラムも掲載しておきます。

Cityクラス

data class City(
    val name: String? = null,
    val state: String? = null,
    val country: String? = null,
    val isCapital: Boolean? = null,
    val population: Long? = null,
    val regions: List<String>? = null
)

getSampleCityListメソッド

private fun getSampleCityList(): List<City> {
    val list = mutableListOf<City>()
    for (i in 0..999) {
        list.add(
            City(
                "LosAngele_${String.format("%03d", i)}", "CA", "USA",
                false, 5000000L, listOf("west_coast", "socal")
            )
        )
    }
    return list
}

パフォーマンス比較

1000件の一括書き込みと逐次書き込みの処理時間を比較してみました。予想はしていましたが、やはり一括書き込みの方が速かったです。

一括書き込みの処理時間
1回目 70ms
2回目 47ms
3回目 61ms

都度書き込みの処理時間
1回目 261ms
2回目 97ms
3回目 189ms

まとめ

set(), update(), delete()のオペレーションを大量に行う場合はパフォーマンスの観点からも一括書き込みを使おう。

参考