データ保存戦略
結論: 保存する方が圧倒的に安い
毎回取得 vs 保存の比較
| 毎回取得 | 保存(キャッシュ) | |
|---|---|---|
| API呼び出し | 検索のたびにYouTube API + 字幕取得 | 初回のみ |
| レスポンス速度 | 5〜30秒(字幕取得に時間かかる) | 0.1〜1秒(DB検索のみ) |
| YouTube APIクォータ | すぐ枯渇(1日10,000ユニット) | ほぼ消費しない |
| レート制限リスク | 高い(BANされる可能性) | 低い |
| DB費用 | 不要 | 月$0〜$25 |
具体例: チャンネルA(動画500本)を100人が1日1回検索した場合
| 毎回取得 | 保存 | |
|---|---|---|
| 字幕取得回数/日 | 50,000回 | 500回(初回のみ) |
| YouTube API消費 | 即クォータ超過 | ほぼゼロ |
| ユーザー体験 | 毎回待たされる | 即時表示 |
→ 毎回取得だと1日で破綻する
おすすめ構成
初回: ユーザーが検索時にチャンネルを指定 → 字幕 を全取得 → Meilisearchに保存
検索: Meilisearchに対してクエリ(YouTube APIを使わない)
差分: 検索時に前回取得以降の新規動画を自動チェックし、あれば差分取得
データ量の見積もり
| 規模 | データ量 |
|---|---|
| 動画1本の字幕 | 5〜50KB |
| 1,000本のチャンネル | 5〜50MB |
| 10,000チャンネル分 | 50〜500GB |
検索速度の対策
| 方法 | 速度 | コスト |
|---|---|---|
PostgreSQL LIKE | 遅い(数秒) | 追加なし |
| PostgreSQL 全文検索 (tsvector) | 速い | 追加なし |
| Meilisearch / Typesense | 爆速(数ms) | +$0〜$30/月 |
| Elasticsearch | 爆速 | +$50〜$100/月(高い) |
初回取得のボトルネックと対策
課題
- 100万本 × 平均3秒 = 約35日(並列化しても数日)
- YouTube側の大量取得によるIP BANリスク
- 60GBのDBに対する曖昧検索のインデックス設計
対策
- 新規チャンネルの字幕取得は インプロセスキュー で順次処理
- 同じチャンネルを複数ユーザーがリクエストしても 1回だけ取得(重複排除)
アクセス権管理(user_video_access)
ユーザーが動画の字幕にアクセス(クレジット消費)した履歴をTursoで管理する。キャッシュキーは user_id + video_id(動画単位)。
テーブル設計
CREATE TABLE user_video_access (
user_id TEXT NOT NULL REFERENCES users(id),
video_id TEXT NOT NULL REFERENCES videos(id),
credits INTEGER NOT NULL, -- 消費したクレジット数
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
expires_at DATETIME NOT NULL, -- created_at + 4週間
PRIMARY KEY (user_id, video_id)
);