第7章 — データベースキャッシュ: 最後の砦
DB の中にもキャッシュがある
「Redis を入れる前に、DB 自体のキャッシュ機能を理解しておくべきだ」とケンジ。
PostgreSQL のキャッシュ階層
Loading diagram...
shared_buffers
PostgreSQL のメインキャッシュ。推奨値は総メモリの 25%。
-- shared_buffers の設定
ALTER SYSTEM SET shared_buffers = '4GB'; -- 16GB RAM の場合
-- キャッシュヒット率の確認
SELECT
sum(blks_hit) AS cache_hits,
sum(blks_read) AS disk_reads,
round(sum(blks_hit) /
(sum(blks_hit) + sum(blks_read))::numeric * 100, 2)
AS hit_ratio
FROM pg_stat_database;INFO
PostgreSQL のキャッシュヒット率は 99% 以上 を目標にする。95% を下回ったら shared_buffers の増加を検討。
work_mem
ソートやハッシュ操作に使うメモリ。クエリごとに割り当てられる。
-- 大きなソートが必要なクエリの前に
SET work_mem = '256MB';
SELECT * FROM products ORDER BY popularity DESC LIMIT 1000;
RESET work_mem;MySQL のキャッシュ
InnoDB バッファプール
MySQL/InnoDB のメインキャッシュ。推奨値は総メモリの 70-80%。
-- バッファプールサイズの設定
SET GLOBAL innodb_buffer_pool_size = 12884901888; -- 12GB
-- ヒット率の確認
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';AWS RDS のキャッシュ関連設定
FreshMarket は RDS for PostgreSQL を使用。キャッシュ関連のパラメータグループ設定:
| パラメータ | 推奨値 | 説明 |
|---|---|---|
shared_buffers | 総メモリの 25% | メインキャッシュ |
effective_cache_size | 総メモリの 75% | クエリプランナーのキャッシュ推定 |
work_mem | 64-256MB | ソート・ハッシュ用 |
random_page_cost | 1.1 | SSD 前提 |
RDS Proxy
RDS Proxy は AWS マネージドの接続プール。Lambda や ECS からの大量接続を効率的に管理する。
Loading diagram...
接続プール
DB 接続の確立は50-100msかかる。接続プールで再利用する。
Loading diagram...
| ツール | 言語 | 特徴 |
|---|---|---|
| PgBouncer | — | PostgreSQL 専用、軽量 |
| ProxySQL | — | MySQL 専用、クエリルーティング |
| HikariCP | Java | JVM 最速 |
クエリ最適化 = 最高のキャッシュ
「最速のクエリは、実行されないクエリだ。次に速いのは、インデックスが効いたクエリだ」
N+1 問題
# ❌ N+1: 商品100件 → 101クエリ
products = Product.all
products.each do |p|
puts p.category.name # 各商品で1クエリ
end
# ✅ Eager Loading: 2クエリ
products = Product.includes(:category).all
products.each do |p|
puts p.category.name # キャッシュ済み
endマテリアライズドビュー
複雑なクエリ結果をテーブルとして保存する。
CREATE MATERIALIZED VIEW popular_products AS
SELECT p.id, p.name, p.price,
COUNT(oi.id) as order_count
FROM products p
JOIN order_items oi ON oi.product_id = p.id
GROUP BY p.id
ORDER BY order_count DESC;
-- 定期的にリフレッシュ
REFRESH MATERIALIZED VIEW CONCURRENTLY popular_products;マナミの DB 最適化
| 施策 | 効果 |
|---|---|
| shared_buffers を 4GB に | ヒット率 96% → 99.2% |
| N+1 を Eager Loading に | クエリ数 80% 削減 |
| 接続プール(PgBouncer) | 接続時間 50ms → 1ms |
| マテリアライズドビュー | 集計クエリ 2秒 → 5ms |
次の章では、複数サーバーにまたがる分散キャッシュの課題と解決策を学ぶ。