🌟

FirestoreのCOUNT()のパフォーマンスを計測してみた

2022/10/24に公開

Firebase Summitでもいろいろ発表されていますね!
https://zenn.dev/mashi/articles/66c1990ddeb849

COUNTはコレクション数に応じて遅くなるのか

巨大なコレクションに対してのクエリがどの程度スピードが変わるのかを簡単に検証してみました

検証に使ったコードはこちら

const measurement = async <T>(f: () => Promise<T>, tag: string) => {
  const r: number[] = [];

  for await (const _ of [...new Array(200).keys()]) {
    const m = await withMetric(f, { showLog: false });
    r.push(m.elapse);
  }

  const min = r.reduce((a, b) => Math.min(a, b));
  const max = r.reduce((a, b) => Math.max(a, b));
  const average = r.reduce((prev, curr) => prev + curr) / r.length;

  console.log(`[${tag}] min: ${min} max: ${max} average: ${average}`);
};

const withMetric = async <T>(
  f: () => Promise<T>,
  option: {
    showLog: boolean;
  } = { showLog: true }
) => {
  const startTime = performance.now(); // 開始時間
  const r = await f();
  const endTime = performance.now(); // 終了時間

  const elapse = endTime - startTime;
  option.showLog && console.log(`millis: ${elapse} `);
  return {
    result: r,
    elapse,
  };
};

測定結果

  • 別のコレクションに対してテストデータを作成し、全件を取得するクエリを発行する
  • 同じクエリを200回ずつ発行して、最小値、最大値、平均値を出力

測定は全て東京リージョンで行っています。単位はms
さすがにコレクションサイズが大きいとクエリのパフォーマンスも影響がありそうですね。
1万件に対して全件カウントした場合、Whereをつけた場合でも大きな差はなさそうです。

ドキュメントカウント 最小値(ms) 最大値(ms) 平均値(ms)
200件 16.13766622543335 383.27662467956543 48.986748945713046
1000件 21.502166748046875 145.2618751525879 32.469205820560454
10000件 52.992416858673096 178.3753752708435 74.26382768392563
50000件 141.8333339691162 485.1029577255249 228.72841580867768
100000件 267.9079155921936 1257.633542060852 426.1588483285904
10000件から3333件取得 27.292333126068115 157.46166706085205 37.517049396038054
50000件から16667件取得 53.39187526702881 348.72037506103516 75.77325768470764

コストに関して

前回記事では1Readしかかからなさそうと書いていたのですが、Firebase summitでは「1000件に対して1Read」と発表されていました。
ですので、100万件にカウントする場合は1000Read発生する計算になりそうです。
公式ドキュメントはこちら
https://cloud.google.com/firestore/pricing#aggregation_queries

Discussion