Cloudflare Workers KVでの複数アイテム一括取得
Cloudflare Workers KVで複数アイテムを効率的に取得する方法を解説。N+1問題を避け、パフォーマンスを向上させるための配列を使った一括取得テクニックを紹介します。
広告ここから
広告ここまで
目次
Cloudflare KVを使っている場合、複数のアイテムをまとめて取得するには、 list
と get
両方を使う必要があります。この方法について簡単にまとめました。
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に伝えれるようにしていきましょう。