Cloudflare Workers KVでの複数アイテム一括取得

Cloudflare Workers KVで複数アイテムを効率的に取得する方法を解説。N+1問題を避け、パフォーマンスを向上させるための配列を使った一括取得テクニックを紹介します。

広告ここから
広告ここまで

目次

    Cloudflare KVを使っている場合、複数のアイテムをまとめて取得するには、 listget 両方を使う必要があります。この方法について簡単にまとめました。

    KVの List メソッドは全てのデータを返さない

    AWSのDynamoDBなどと同じイメージで使うとちょっと面食らうのですが、KVの List APIはキーの名前やmetadataなど一部の情報のみを返します。

    response: Promise<{ keys: { name: string, expiration?: number, metadata?: object }[], list_complete: boolean, cursor: string }>

    そのため、一覧データを取得したい場合などでは、 get APIも併用する必要があります。

    get API で N+1 クエリを起こしやすい

    ここで注意が必要なのは、「 get で取らないといけないのか、ならループで取るか」とやってしまうことです。これをやると、N+1 クエリ問題が発生してパフォーマンスがガタ落ちします。

    // 問題のあるコード
    async getNumbers(owner: string): Promise<NumberItem[]> {
      const list = await this.kv.list({ prefix: 'number:' }); // 全KVエントリ取得
      const numbers: object[] = [];
      for (const key of list.keys) {
        const data = await this.kv.get(key.name); // N+1問題
        if (data) {
          const numberItem: NumberItem = JSON.parse(data);
          numbers.push(numberItem);
        }
      }
      return numbers;
    }
    

    KV の get はキーを配列でうけとれる

    これは最近まで知らなかったのですが、KV の get は引数に100件まで配列でキーを受け取れます。なのでループで get するのではなく、list APIで取得したデータからキーとなる name だけの配列を生成する形にすれば、 KV へのリクエスト量を減らせます。

    
        const keys = list.keys.map(key => key.name);
        const items = await this.kv.get(keys);
        const numbers: NumberItem[] = [];
        
        for (const [key, value] of Object.entries(Object.fromEntries(items))) {
          if (value && typeof value === 'string') {
            try {
              const parsedItem = JSON.parse(value) as NumberItem;
              numbers.push(parsedItem);
            } catch (error) {
              console.error(`Failed to parse item from key ${key}:`, error);
            }
          }
        }

    生成 AI にコーディングさせると、高確率で N + 1 の実装が出てきます。知らぬ間にパフォーマンス問題を内包する前に、KVの仕様を理解してAIに伝えれるようにしていきましょう。

    参考記事

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark