🏠 ホーム
プログラミング
インフラ
フリーランスCTO
DB
完全無料ツールまとめ
マーケティング
経済市場
政治経済
教育

RDB限界説の真実と現代RDSアーキテクチャの最適解

  DB >  

はじめに

2010年代以降、Web業界では

といった考え方が広く浸透しました。

しかし、現在のハードウェア性能やRDBの内部構造を踏まえると、その多くは当時の環境や設定に起因する誤解であり、必ずしも技術的な真実ではありません。

本稿では、

について整理します。


「NoSQL/検索エンジンのインメモリ神話」の正体

2010年代前半の業界トレンド

Web2.0やビッグデータブームの中で、

RDBは古くて遅い。
これからはMongoDBやElasticsearchの時代だ。

という考え方が急速に広まりました。

しかし、その背景には大きな誤解が存在していました。


誤解の原因:MySQLデフォルト設定の罠

当時のMySQL(InnoDB)の初期設定では、

innodb_buffer_pool_size = 128MB

程度しかメモリが割り当てられていませんでした。

そのため、

という状況が発生していました。

一方で、

などはインストール直後から大量のメモリを使用する設計でした。

その結果、

MySQL → 遅い
NoSQL → 速い

という印象だけが広まりました。


実際は何が起きていたのか

現代のMySQLやPostgreSQLでは、

に十分なメモリを割り当てれば、

をほぼ完全にメモリ上で処理できます。

特に単純検索では、

B-Treeインデックス

の方が、

よりも圧倒的にメモリ効率が良く、

で動作します。

つまり、

NoSQLが速かったのではなく、MySQLがまともにメモリを与えられていなかった

というのが実態です。


「システムを速くしたいからElasticsearch」の罠

現在でも、

システムが重いからElasticsearchを入れよう

という提案は頻繁に出てきます。

しかし、

全文検索要件が無い

のであれば、多くの場合で逆効果になります。


問題① データの二重管理

RDBとElasticsearchを併用すると、

MySQL
↓
同期
↓
Elasticsearch

という構成になります。

すると、

が必ず発生します。

エンジニアは常に

なぜ検索結果とDBが違うのか

という調査に追われることになります。


問題② 運用コスト増大

Elasticsearchの実体は

Lucene(Java)

です。

そのため、

が必要になります。

結果として、

DBを一つ増やしただけ

のつもりが、

実際には巨大なJavaシステムを一つ運用することになります。


本来やるべきこと

多くの場合、

まずはインデックスがメモリ上にあるか確認が先決です。

postgresで

SELECT 
    relname AS テーブル名,
    heap_blks_read AS ディスクから読んだデータブロック数,
    heap_blks_hit AS メモリから読んだデータブロック数
FROM pg_statio_user_tables
WHERE relname = '商品テーブル名';


「とりあえずRedisキャッシュ」の問題点

Redisは非常に優秀な技術ですが、

何でもRedisに載せるという考え方には大きな問題があります。


キャッシュミス・ペナルティ

キャッシュヒット時は高速です。

しかしキャッシュミス時には、

Redisへ問い合わせ
↓
データ無し
↓
RDSへ問い合わせ

となります。

つまり、

の二重コストが発生します。


Cache Stampede

さらに危険なのが、

です。

高負荷時にキャッシュが一斉に失効すると、

大量のリクエストが一気にRDSへ流れ込みます。

結果として、

Redis
↓
素通り
↓
RDS直撃

となり、

RDSが一瞬で過負荷になります。


Redisのメモリ効率は良くない

Redisは

JSON
Key-Value

としてデータを保持します。

つまり、

商品情報全体を丸ごとメモリに載せることになります。


MySQLのB-Treeは極めて効率的

一方でMySQLは、

圧縮されたB-Treeインデックスを保持します。

例えば、

商品 600万件
インデックス 15本

程度なら、

インデックス全体は数GB程度で収まります。

つまり、

Redisに数十GB投資

するより、

RDSメモリ増設

の方が圧倒的に費用対効果が高いケースが多いのです。


最大の負債:キャッシュ整合性

キャッシュを導入した瞬間から、エンジニアは

キャッシュ無効化(Cache Invalidation)

という永遠の問題を抱えます。

例えば、

が発生した際、

Redis側を正確に消さなければ、

古いデータが表示され続けます。

この問題は想像以上に開発工数、運用工数を奪います。


Aerospike・Couchbaseが普及しきらない理由

Aerospike

Aerospikeは

インデックス=メモリ
データ=SSD

という理想的な設計です。

しかし現場では、

Redisで十分では?

という壁があります。


理由

だからです。

技術的優位性だけでは採用されません。


Couchbase

Couchbaseも優秀です。

しかし真価を発揮するには、

が必要になります。


問題

600万件程度では、

という状況になりやすいです。


600万件・15インデックスの現実

実際のメモリ消費

条件:


理論値

インデックスやポインタを含めると、

実質数GB規模になります。


実運用

断片化や余裕領域を考慮すると、

約5〜6GB

程度になります。

さらに、

を考慮すると、

9〜12GB

程度が必要になります。

そのため、

最低16GBクラスのRDS

が現実的な選択になります。

ただし、これは一つのテーブルでの話で通常100テーブル以上で運用する事になると常時メモリのインデックスは使えないという事になります。


「RDSは遅い」の正体

多くの人がRDSの限界だと思っている現象は、実際には

Eviction
↓
Thrashing

です。


Eviction

Buffer Poolが不足すると、

重要なインデックスが追い出されます。


Thrashing

追い出されたインデックスを、毎回SSDから再読込します。すると、

が発生します。これを見たエンジニアが、

RDSが限界だ

と誤解するのです。


現代メガベンチャーが辿り着く構成

最終的に多くの大規模サービスは、

以下の思想に収束しています。


① RDSを正しく使う

へ十分なメモリを与える。

まずはここからです。


② Textを物理分離する

商品説明などは、

別テーブルまたは別DBへ移動する。

メインテーブルは極限まで軽量化する。


③ JOINを禁止

必要なデータは、アプリケーション側で取得して結合する。これにより、

が可能になります。


④ シャーディングで水平分割

JOIN禁止した結果、ユーザー単位やテーブル単位で物理分割しやすくなります。

これにより、サーバー追加によるスケールアウトが可能になります。


総括

「RDB限界説」の多くは、実際にはRDBそのものの限界ではなく、

によって引き起こされた問題です。

高負荷システムにおける王道は、

  1. 長文Textを分離する

  2. インデックスをBuffer Poolへ常駐させる

  3. 不要なRedisやElasticsearchを増やさない

  4. JOIN依存を減らす

  5. 最後にシャーディングする

という極めてシンプルな構成です。

流行のミドルウェアを追加する前に、まずRDBのメモリ設計とデータ配置を見直すことが、最も高速で、最も安価で、最も保守性の高いアーキテクチャにつながります。

登録日:

更新日:

by

コメント         tweetでコメント