🗄️
概念 #Cloudflare #D1 #SQLite #データベース 📚 ブログサイト構築

ブログサイト構築 — Cloudflare D1 入門

Cloudflare エッジで動くサーバーレス SQLite、D1 の概要。KV との違い・Pages Functions からの利用方法・ブログへの応用例

Cloudflare D1 とは

Cloudflare が提供するサーバーレス SQLite データベース。 Workers / Pages Functions から SQL クエリを直接実行できる。

Pages Functions
  └─ env.DB.prepare("SELECT * FROM posts WHERE id = ?")
      └─ Cloudflare D1(SQLite)

KV との違い

特性Cloudflare KVCloudflare D1
データモデルKey-Value(文字列)リレーショナル(SQL)
クエリget(key) / put(key, val)SQL(SELECT / JOIN / 集計)
整合性結果整合性強整合性(ローカルコピー)
用途キャッシュ・カウンタ・設定構造化データ・関係クエリ
無料枠読み 100k/日・書き 1k/日5M 行読み/月・100k 行書き/月

KV の適用場面:

  • 読み取りが圧倒的に多い(閲覧数カウントなど)
  • 厳密な整合性が不要

D1 の適用場面:

  • 構造化データ(ユーザー・コメント・タグなど)
  • JOIN や集計クエリが必要
  • トランザクションが必要

D1 のアーキテクチャ

D1 は SQLite を Cloudflare のエッジで動かす。 1 つのリージョンがプライマリとなり、読み取りはエッジにキャッシュされる。

Write → Primary (Cloudflare DC)
Read  → エッジキャッシュ(数ミリ秒遅延の可能性)

KV のグローバル分散とは異なり、D1 は単一プライマリ + リードレプリカの構成。

基本的な使い方

1. データベース作成

wrangler d1 create my-blog-db

2. wrangler.toml にバインディング追加

[[d1_databases]]
binding = "DB"
database_name = "my-blog-db"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

3. スキーマ作成

-- schema.sql
CREATE TABLE comments (
  id       INTEGER PRIMARY KEY AUTOINCREMENT,
  post_id  TEXT    NOT NULL,
  content  TEXT    NOT NULL,
  author   TEXT    NOT NULL,
  created  TEXT    NOT NULL DEFAULT (datetime('now'))
);
wrangler d1 execute my-blog-db --file=schema.sql

4. Pages Functions からクエリ

interface Env {
  DB: D1Database;
}

export const onRequest: PagesFunction<Env> = async ({ env, params }) => {
  const postId = params.slug as string;

  const { results } = await env.DB.prepare(
    'SELECT * FROM comments WHERE post_id = ? ORDER BY created DESC'
  ).bind(postId).all();

  return Response.json(results);
};

ブログへの応用例

コメント機能

CREATE TABLE comments (
  id       INTEGER PRIMARY KEY AUTOINCREMENT,
  post_id  TEXT NOT NULL,
  author   TEXT NOT NULL,
  content  TEXT NOT NULL,
  created  TEXT NOT NULL DEFAULT (datetime('now'))
);

タグ集計

SELECT tag, COUNT(*) as count
FROM post_tags
GROUP BY tag
ORDER BY count DESC
LIMIT 20;

閲覧数(KV からの移行例)

CREATE TABLE views (
  slug   TEXT PRIMARY KEY,
  count  INTEGER NOT NULL DEFAULT 0
);

-- 閲覧時
INSERT INTO views (slug, count) VALUES (?, 1)
ON CONFLICT (slug) DO UPDATE SET count = count + 1;

KV より D1 の方が厳密なカウントが必要な場合に適している。 (KV は結果整合性のため、高頻度書き込みでカウントが失われる可能性がある)

本サイトでの位置づけ

現在の本サイトは閲覧数カウントに Cloudflare KV を使用している。 シンプルな用途には KV で十分だが、以下が必要になれば D1 への移行を検討する。

  • コメント機能の追加
  • タグ・シリーズの動的集計(ビルド時でなくランタイムで)
  • 複数記事にまたがる統計クエリ

D1 の制限(2025年時点)

項目制限
データベースサイズ2GB(Workers Paid)/ 500MB(Free)
行読み取り/月25M(Paid)/ 5M(Free)
行書き込み/月50M(Paid)/ 100k(Free)
同時接続Workers Isolates ごとに 1 接続

関連