ユースケース別NoSQL選定ガイド: 「こういうときはどのNoSQL?」を逆引きする

『NoSQLの4分類を整理する: KVS・ワイドカラム・ドキュメント・グラフの本質的な違い』 ではデータモデル単位の整理を扱いました。

『主要NoSQLプロダクトリファレンス: Redis・Cassandra・DynamoDB・MongoDB・Neo4j を中心に』 ではプロダクト単位の整理を扱いました。

本記事はその上のレイヤとして「このユースケースならどのプロダクトを使うか」を逆引きで整理します。

NoSQL選定で最初に詰むのは「NoSQLを使う」と言ったまま固有プロダクトの議論に飛んでしまうパターンです。ユースケースの要件(クエリパターン・整合性・スケール・データ構造)を分解してから、それに合うデータモデル → プロダクトの順に絞り込むのが現実的です。本記事はそのフローに沿って、典型ユースケースごとの推奨プロダクトと、それを選ぶ理由をまとめます。

そもそもNoSQLで解決すべき課題か

NoSQLに置き換える前に、「その課題は本当にNoSQLで解くべきか」を確認します。RDB(OLTP)の課題に対して、NoSQLの解決可能性は一律ではありません。

RDB(OLTP)で困っていることNoSQLで解けるか推奨されるアプローチ
クエリ・検索の性能が出ない○ ボトルネックが分散できれば有効KVS / ドキュメントDBへシャーディング
データレイテンシを下げたいKVS / ドキュメントDB
初期導入コストを下げたいスケールアウト前提のプロダクトでスモールスタート
トランザクション性能を上げたい△ データモデル次第単一ドキュメント/単一エントリに収まればNoSQLでも可
パフォーマンスチューニングを簡単にしたい△ プロダクト次第KVSは「複雑クエリがそもそも書けない」のでチューニング不要
非構造データを扱いたい△ 半構造(JSON等)なら○、メディアは×動画・音声はオブジェクトストレージ+メタデータをNoSQL
運用管理コストを削減したい△ クラウドなら○、オンプレは怪しいマネージド(DynamoDB / Cosmos DB / Atlas等)
バッチ集計を速くしたい×RDB(DWH) / Hadoop / Spark
大量データの初期ローディングを速くしたい×RDB(DWH) / Hadoop

特に勘違いしやすいのがバッチ集計です。NoSQLのMapReduceやアグリゲーションを使えばできますが、それは「やれる」のレベルで、専用のDWHやHadoopに最適化されたものに比べて速くはありません。NoSQLは基本的にオンライン処理(OLTP的なリアルタイム読み書き)に効く道具と捉えます。

ボトルネックが分散できないケース(ネットワーク帯域がネック、JOINだらけのワークロード、強整合性で複数行を更新するトランザクション中心)は、KVSにしてもクエリは速くなりません。先にRDB(OLTP)のチューニング余地を潰したか、NoSQLに置き換えても分散の利益が出るかを確認します。

データモデル選定の判断軸

NoSQLを使うと決めたら、プロダクト名から入らずまずどのデータモデルかを決めます。データモデルはクエリパターンとデータ構造で決まります。

判断軸 選択肢 適するデータモデル
クエリパターン キー検索のみ KVS
キー+カラム単位の取り出し・時系列範囲スキャン ワイドカラム
半構造データの絞り込み・集計 ドキュメント
ノード間の関係性探索(経路・近傍・類似度) グラフ
データ構造 単純な値・文字列・数値 KVS
同じキーに対して大量の列を時系列に積む ワイドカラム
スキーマが行ごとに違う半構造(JSON的) ドキュメント
エンティティ間の関係性が主役 グラフ

プロダクト選定の判断軸

データモデルが決まったら、同じモデル内でプロダクトを絞り込みます。整合性・スケール・地理分散はデータモデルでは決まらず、プロダクト固有の特性で選びます。

判断軸 選択肢 候補プロダクト
整合性要件 複数行ACIDが必須 RDB / DynamoDB(TransactWriteItems)/ MongoDB 4.0+(マルチドキュメントトランザクション)/ Cosmos DB(ストアドプロシージャ内)
単一文書/単一エントリ内の原子性で十分 ほぼすべてのNoSQL
結果整合性で許容 Cassandra / DynamoDB / Riak / Couchbase XDCR
スケーラビリティ 単一ノードで足りる Redis単体 / Neo4j単体 / RDB
水平スケールを前提に組みたい Cassandra / DynamoDB / MongoDB(シャード)/ HBase / Couchbase
地理分散 シングルDCで十分 何でも可
マルチDCでフェイルオーバーできればよい MongoDBレプリカセット / Redisレプリケーション
マルチDCで双方向書き込みしたい Cassandra / Couchbase XDCR / DynamoDB Global Tables / Cosmos DB
運用形態 フルマネージドで運用したくない DynamoDB / Cosmos DB / MongoDB Atlas / Couchbase Capella / ElastiCache
OSSをオンプレ/マルチクラウドで動かしたい Cassandra / MongoDB / Redis / Couchbase / Neo4j / HBase

クエリパターンとデータ構造でデータモデルを決めて、整合性・スケール・地理分散・運用形態でプロダクトを絞る、という二段階で考えます。

シャーディングの方式(レンジ・ハッシュ・リバランシング)は、同じ「水平スケール対応」と言われるプロダクトでも個性が出る部分です。詳細は 『シャーディング / パーティショニング戦略: レンジ・ハッシュ・リバランシング・ルーティング』 で扱っています。

ユースケース別逆引き

ここから本題です。実務でよく出会うユースケースに対して、推奨プロダクトと選ぶ理由を整理します。

キャッシュ・セッション管理

キャッシュやセッション管理は、圧倒的に読み取り中心・低レイテンシ・TTLでの自動失効が要件です。整合性は緩くてよい(多少の遅延は許容)ケースが多いです。

第一候補はRedis(マネージドならElastiCache / Azure Cache for Redis)、代替はMemcachedです。

選ぶ理由は以下の通りです。

  • メモリ上でミリ秒以下の応答が出せる
  • TTL(EXPIRE)で失効をDB側に任せられる
  • Hash型を使えば「ユーザID → プロファイル一式」を1キーでまとめられる(Memcachedより使いやすい)
  • レプリケーション・Clusterでリニアにスケールする

Memcachedとの使い分けは、「文字列とメタデータがあれば十分・サーバ単純さ重視・マルチスレッドで高スループット」ならMemcached、永続化・データ構造・Pub/Sub・Luaが要るならRedisです。実質Redisで困らないことが多いです。

リアルタイムランキング・タイムライン

スコア順でのTop-N取り出し、スコア更新の頻発、書き込みも読み込みも速い、というのが要件です。

第一候補はRedis(Sorted Set)です。

Sorted Setは要素にスコアを付けて常にソートされた状態で保持し、ZADD / ZRANGE / ZINCRBYが対数時間で動きます。ゲームのスコアランキング、ニュースフィードの新着順、ツイッターの逆時系列タイムラインなどはこれ一本で組めます。RDBのORDER BY score LIMIT 100を毎回叩く設計はランキング規模が大きくなると詰みます。

レート制限・カウンタ

「直近1分で何回呼ばれたか」「日次の利用回数」のような単純カウンタを、原子的にインクリメントするユースケースです。

第一候補はRedis(INCR + EXPIRE)です。

INCRが原子的、EXPIREで時間窓を持てます。スライディングウィンドウならSorted Setにタイムスタンプを積むパターンも定番です。

Pub/Sub・メッセージブローカー

ノード間でのファンアウト配信、軽量なメッセージングが要件です。

第一候補はRedis(Pub/SubまたはStreams)です。本格的なメッセージブローカーが要るならKafka / RabbitMQが候補になります。

チャットのreply通知やWebSocketサーバ間のメッセージ伝播のような配信即捨ての用途はRedis Pub/Subで十分です。耐久性・コンシューマグループ・再配信が要るならStreams、それ以上に堅牢な保証が要るならKafkaに上げます。

ジョブキューイング・非同期ワーカー

バックグラウンドジョブをワーカープールに配布、ある程度の永続性、リトライ、優先度付け、可視性タイムアウト(処理中ワーカー死亡時の再配信)が要件です。

第一候補はRedis(List + BRPOP / Streams + Consumer Group)です。本格的に組むならAWS SQS、リッチなルーティングが要るならRabbitMQ、超大量・ストリーム処理ならKafkaが候補になります。

選定理由は以下の通りです。

  • Sidekiq(Ruby)/ Resque / RQ(Python)/ Bull(Node.js)など、各言語の定番ジョブキューライブラリはRedisをバックエンドとして採用している
  • List + BRPOPでFIFOのシンプルなジョブキューが組める
  • Streams + Consumer GroupはメッセージACK・再配信・コンシューマ単位のオフセット管理が組み込みで、信頼性の要る配信に向く
  • 永続化(AOF)でプロセス再起動を跨いでもジョブを失わない設計にできる

選び分けは以下のようになります。

  • 既にアプリでRedisを使っていて、軽めのジョブキュー
    • Redis上の専用ライブラリを使う
  • AWSでフルマネージド・運用ゼロにしたい
    • SQS(標準キューまたはFIFOキュー、Lambdaトリガと相性がよい)を選ぶ
  • Pub/Sub的なファンアウト・優先度・dead letter queue・トピック交換が要る
    • RabbitMQを使う
  • イベントソーシング・大量ストリーム・リプレイが要る
    • Kafkaに上げる

「ジョブキューをNoSQLで組むか」という発想ではなく、まず専用のキューサービス/メッセージブローカーが要件を満たすかを確認するのが先です。Redisが一番手軽ですが、配信保証・順序保証・dead letter queueなどの要件が厳しくなるほど専用品が有利になります。

IoT・時系列・センサーデータ

数千〜数万のセンサーから毎秒書き込み、24/365の継続稼働、特定期間のデータをまとめて取り出す、書き込みが圧倒的に多い、リニアスケール必須、というのが要件です。

第一候補はCassandraです。AWS中心ならDynamoDB、Azure中心ならCosmos DB(Cassandra API)が候補になります。専用品ならTimescaleDB / InfluxDB / Amazon Timestreamなど時系列特化の選択肢もありますが、汎用NoSQLの中ではCassandraが定番です。

選定理由は以下の通りです。

  • マスターレスのリング型クラスタで単一障害点がない
  • ノード追加でほぼリニアに書き込みスループットが伸びる
  • ワイドカラムは「センサーID + 日付」をパーティションキー、「タイムスタンプ」をクラスタリングカラムにする設計と相性が抜群(1行が時系列バケットになり、1日分を1行で取れる)
  • スパース(センサーAは毎秒、Bは30分ごと)なデータでも追加カラムだけで済む

書き込みスループットが伸びる構造的な理由は、CassandraがLSM tree系のストレージエンジンを採用していることに由来します。詳細は 『ストレージエンジンの2大潮流: B-tree と LSM tree の構造比較』 を参照してください。

RDBだと毎秒数万件のINSERTで書き込み側が詰まる、INDEX維持コストが効く、シャーディングを自前で組む必要がある、といった問題が連鎖します。

ユーザ行動ログ・イベントトラッキング

大量のappend-only書き込み、ユーザID単位での履歴取り出し、ある程度の時系列範囲指定が要件です。

第一候補はCassandra、AWS中心ならDynamoDB(パーティションキー = ユーザID、ソートキー = タイムスタンプ)、Azure中心ならCosmos DBが候補になります。

時系列IoTと要件が近いです(書き込み中心 + キー単位の時系列レンジ)。マネージドで楽したい・運用負荷を抑えたいならクラウドネイティブ、オンプレ・マルチクラウドならCassandraです。

メッセージング基盤(チャット履歴)

24/365で止められない、ユーザ数・メッセージ数が膨大、ピーク負荷耐性、低レイテンシ、書き込み中心が要件です。

第一候補はCassandra、AWS中心ならDynamoDBも候補です。

マスターレス・分散・リニアスケール・高可用性という要件が綺麗に揃います。Discord、Instagram、Netflixの各種メタデータといった大規模事例もCassandra系です。チャットルームIDをパーティションキー、メッセージタイムスタンプをクラスタリングキーにする設計が定番です。

IF NOT EXISTSのLightweight Transaction(CAS)でユーザID重複登録を防ぐなど、限定的な強整合性も組み込めます(ただしパフォーマンスペナルティはあります)。

Webアプリのバックエンド(半構造データ)

スキーマが画面・モデル単位で違う、開発スピード重視、JSONとの往復が多い、サブドキュメントの絞り込み・集計が要る、というのが要件です。

第一候補はMongoDB(オンプレ/マルチクラウドなら自前またはAtlas)です。AWS中心ならAmazon DocumentDB(MongoDB互換API)も候補、Azure中心ならCosmos DB(SQL APIまたはMongoDB API)が候補です。

選定理由は以下の通りです。

  • 1つのドキュメントにネストしたオブジェクト・配列をそのまま入れられる
  • スキーマレスで属性の追加・変更にマイグレーションが要らない
  • Aggregation PipelineでSQLのGROUP BY / JOIN相当をある程度カバーできる
  • 4.0以降のマルチドキュメントトランザクションでクリティカルな複数文書更新もサポート

注意点として、強整合性の複数行更新が中心の業務(金融基幹・在庫の厳密な引当)は依然としてRDBの方が素直です。MongoDBのトランザクションは使えますが、得意領域ではありません。

ECサイトの商品カタログ管理

アイテムごとに属性が違う(家電 vs 衣類 vs 食品)、属性追加が頻繁、商品担当者が直接データを見る、シャーディングで商品数の増加に耐えたい、というのが要件です。

第一候補はMongoDBです。AWS中心ならAmazon DocumentDB、Azure中心ならCosmos DBも候補になります。

スキーマレスで「カテゴリごとに違う属性」をそのままJSONとして持てます。ALTER TABLE相当が要らないので、属性追加で業務停止を起こしません。JSONは商品担当者でも読み書きしやすいです。シャーディングはハッシュ・レンジ・複合キーから選べます。

注意点として、課金・在庫トランザクションはRDBに分けるハイブリッド構成が一般的です。何でもMongoDBに突っ込まないのが鉄則です。

ログ集約システム(Fluentd系)

フォーマットがバラバラのログを大量に書き込む、時刻で絞ってアドホックに集計したい、リアルタイムに障害調査したい、古いデータは自動削除、というのが要件です。

第一候補はMongoDB、専用ならElasticsearch / OpenSearchです。

FluentdがJSON化したログをそのまま投げ込め、コレクションも自動作成されます。クエリで時刻絞り込み + エラーレベル集計ができます。TTLインデックスで古いログを自動削除できます。BIツールとも繋げやすいです。Hadoopでも同じことはできますが、リアルタイム性でMongoDBが勝る場面が多いです。

全文検索で本格的に切れ込みたいならElasticsearch / OpenSearchの方が向きます。

業界横断アプリ(複数ベンダのデータ集約)

不動産・音楽配信・電子カルテのように、ベンダごとに属性が違うデータを1つのアプリで扱う、新規属性が増え続ける、共通基本属性 + ベンダ固有属性、というのが要件です。

第一候補はMongoDBです。

スキーマレスでベンダ間の属性差を吸収できます。新規属性が来てもスキーマメンテが要りません。JSONのフィールドにインデックスを張れば横断検索もできます。

高速プロトタイプ・アジャイル開発

テーブル定義の手間を省きたい、JS / Ruby等のオブジェクトをそのまま保存したい、Web API(JSON)と相性のよいDBがほしい、というのが要件です。

第一候補はMongoDBです。

JSON ↔ ドキュメントが1:1でORマッパー設定が要りません。MEAN(MongoDB + Express + Angular + Node.js)スタックやMeteorのように、フロント〜バック〜DBがJSONで貫通する構成と相性が抜群です。情報・ノウハウも豊富で詰まりにくいのも利点です。

グラフ問題: 詐欺検知・経路探索・人材マッチング・レコメンド

エンティティ間の関係性そのものがクエリの主役、多段の結合・自己参照・近傍探索、最短経路、類似性、というのが要件です。

第一候補はNeo4jです。

グラフ構造をそのまま格納でき、Cypherで(start)-[*]->(end)のような関係パターンを直感的に書けます。shortestPath()などのアルゴリズムが組み込みです。RDBの自己結合・再帰CTEで同じことをやると、結合段数とともに指数的に遅くなり、SQLも読めない代物になります。

代表的な適用先は以下の通りです。

  • 詐欺検知
    • 同一IP / Cookie / クレジット番号で結ばれる怪しいクラスタを検出する
  • 経路計算
    • カーナビ、物流のCO2 / 燃費 / 所要時間最適化
  • 人材マッチング
    • スキル・経験・プロジェクトの類似度検索
  • ソーシャルグラフ
    • 友達の友達、相互フォロー、コミュニティ抽出
  • レコメンド
    • 「このアイテムを買った人がよく買うもの」のグラフトラバーサル

アンチパターンとして、グラフDBを「スケーラビリティが欲しいから」という理由で選ばないことです。グラフDBはクエリの種類(関係性探索)で選ぶ道具で、書き込みスループットなら他のモデルの方が有利です。

モバイル・サーバ間のデータ同期

端末でオフライン時も動かしたい、再接続時に自動同期、双方向更新、自前で同期機構を組みたくない、というのが要件です。

第一候補はCouchbase(Couchbase Lite + Sync Gateway + Couchbase Server)です。

モバイル端末にCouchbase Liteを組み込んでローカルDBとして動かし、Sync Gateway経由でサーバ側Couchbase Serverと自動同期する設計が標準提供されています。電波が不安定な状況でも動き、双方向更新ができます。代替としてCouchDBのPouchDB連携、Firebase Realtime Database / Firestoreも同種の用途に使えます。

グローバル展開・マルチデータセンタ

複数DCに同じデータを置きたい、各DCのローカルからの書き込みを許したい、DC間でのレプリケーション、災害対策、というのが要件です。

第一候補はCassandraまたはCouchbaseです。AWS中心ならDynamoDB Global Tables、AzureならCosmos DBが候補になります。

選定理由は以下の通りです。

  • Cassandra
    • マスターレスのリング型でリージョン横断のレプリケーションが組み込み
    • 整合性レベル(LOCAL_QUORUMなど)でローカルDC内に閉じた読み書きも可能
  • Couchbase
    • XDCR(Cross Data Center Replication)で双方向レプリケーションができる
    • フィルタリングもサポート
  • DynamoDB Global Tables
    • マネージドのアクティブ-アクティブマルチリージョン
  • Cosmos DB
    • もともとグローバル分散を前提にした設計で、5段階の整合性レベルから選べる

シングルマスターのレプリケーション(書き込みは1拠点に集約)でよいなら、MongoDBのレプリカセット + 各リージョンにSecondaryを置く構成でも回ります。詳細は 『レプリケーション戦略: シングルリーダー・マルチリーダー・リーダーレスの使い分け』 を参照してください。

Hadoopバッチ結果のオンライン提供

既存のHadoop / Sparkで計算したバッチ結果(レコメンド、集計、機械学習モデル出力等)を、Web画面やAPIから低レイテンシで返したい、HDFS運用が既にある、というのが要件です。

第一候補はHBaseです。

HBaseはHDFS上に構築され、Hadoopと同じJavaエコシステムで動きます。MapReduce / Sparkの出力OutputFormatにHBaseを直接指定でき、計算結果をそのままKVストアとしてオンラインから引けます。Spark MLlibのイテレーション中の中間データ参照・更新にも使えます。

注意点として、HBase単体(Hadoop環境なし)で使うのは割に合いません。HDFSクラスタの運用負荷が乗るので、ただのKVSとしてはCassandraやDynamoDBの方が楽です。既にHadoop環境があることが採用前提になります。

同カテゴリ内の使い分け

ここまでで「どのモデル? どのプロダクト?」は概ね決まります。最後に、近いポジションのプロダクト同士の選び分けを整理します。

Redis vs Memcached

観点RedisMemcached
データ型文字列・リスト・セット・ハッシュ・ソート済セット・ストリーム文字列のみ
永続化RDB / AOFなし
Pub/Subありなし
マルチスレッド基本シングルスレッド(I/O部分は別)マルチスレッド
クラスタRedis Clusterクライアント側シャーディング

ほとんどのケースでRedisを選んで困りません。Memcachedが勝つのは「文字列キャッシュだけでよくて、マルチスレッドの極端なスループットを1台で出したい」場面に限ります。

Cassandra vs DynamoDB

両者ともマスターレスのDynamo系で要件は重なります。

  • Cassandra
    • OSS、オンプレ可、マルチクラウド可、CQLでテーブル定義、運用は自前
  • DynamoDB
    • AWSマネージド、運用負荷ゼロ、AWSの他サービスと深く統合、AWSロックイン

AWS専業ならDynamoDB、マルチクラウド・オンプレ・自前運用力があるならCassandraです。

MongoDB vs Couchbase vs Cosmos DB

観点MongoDBCouchbaseCosmos DB
普及度・情報量多い中(クラウド側)
クエリ言語独自(aggregation)N1QL(SQLライク・CRUD全対応)SQLライク(SELECT中心)+ 各API
結合集計内のみありAPI依存
トランザクション4.0+で対応単一文書中心ストアドプロシージャ内で対応
モバイル連携×○(Couchbase Lite)×
マルチDCレプリカセットでSecondary配置XDCRで双方向標準でグローバル分散
運用自前 / Atlas自前 / CapellaAzureマネージド

迷ったらMongoDBが無難です(情報量が圧倒的で、情報詰まり時に解決策が出てきやすい)。SQLライクでCRUD全部やりたい・モバイル同期が要るならCouchbase。Azure中心 + マルチモデル + 整合性5段階ならCosmos DBが候補になります。

Cassandra vs HBase

観点CassandraHBase
アーキテクチャマスターレスマスタースレーブ
前提インフラ単独HDFS / Hadoopが必要
Hadoop統合
単独運用負荷低い高い(HDFS込み)

Hadoop環境前提ならHBase、それ以外はCassandraです。HBaseを「ただの分散KVS」として単独で使うのは割に合いません。

RDB vs NoSQLの判断フロー

NoSQLに飛びつく前のチェックフローです。

flowchart TD
    Q["データ処理の課題は何か?"]
    Q --> A1["バッチ集計・<br/>大量データ初期ロード"]
    A1 --> R1["RDB(DWH) / Hadoop / Spark"]
    Q --> A2["ACIDで複数行を<br/>厳密に更新する基幹業務"]
    A2 --> R2["RDB(OLTP)で<br/>スケールアップ"]
    Q --> A3["クエリ性能・レイテンシ・<br/>スケーラビリティ・<br/>スキーマ柔軟性"]
    A3 --> N["NoSQLの検討に進む"]
    N --> N1["キー検索のみ"]
    N1 --> P1["KVS<br/>(Redis / DynamoDB / Memcached)"]
    N --> N2["半構造データの<br/>絞り込み・集計"]
    N2 --> P2["ドキュメントDB"]
    N --> N3["時系列 /<br/>スパースな大量列"]
    N3 --> P3["ワイドカラム"]
    N --> N4["関係性探索"]
    N4 --> P4["グラフDB"]
    Q --> A4["よくわからない"]
    A4 --> R4["「困っていることは何か?」<br/>から再定義"]

「とりあえずNoSQL」ではなく、RDBのスケールアップで足りるか、足りない理由は何かを先に詰めます。スケールアップで足りるならRDBが一番運用が楽です。

ありがちなアンチパターン

強整合性が必要な決済処理を、結果整合性のみのNoSQLに乗せる

問題は、残高や在庫の二重引き落としリスクです。

対策は、決済・残高はRDBか、ACIDトランザクションを確実にサポートするNoSQL(DynamoDBのTransactWriteItems / MongoDBのマルチドキュメントトランザクション)を使うことです。ただしNoSQLのACIDは得意領域ではないので、得意な道具(RDB)が他にあるならそちらを選びます。

全部MongoDBに突っ込む

問題は、決済・在庫・売上集計など、本来RDBが得意な領域もMongoDBに集約してしまう構成になることです。トランザクションは入ったとはいえ得意領域ではないので、生産性も性能も落ちます。

対策は、商品カタログ・コンテンツ・ログのようにスキーマが揺れる部分はMongoDB、決済・在庫・課金はRDBのハイブリッド構成にすることです。

JOIN多用の業務をMongoDB / Couchbaseで組む

問題は、ドキュメントDBは結合に弱いことです(MongoDBは集計内のみ、Couchbaseは対応するがSQLほどの最適化はない)。RDBなら1行で書けるJOINが、ドキュメントDBではアプリケーション側のループになり、N+1でレイテンシが伸びます。

対策は、そのワークロードはRDBに任せることです。ドキュメントDBを選ぶなら、最初からJOINしなくていいスキーマ設計(埋め込み・参照の事前マテリアライズ)にします。

グラフ問題をRDBの自己結合・再帰CTEで解こうとする

問題は、ソーシャルグラフや経路探索をRDBで組むと、結合段数とともに性能が指数的に劣化することです。

対策は、関係性探索が主役なら最初からNeo4jを採用することです。少量・浅い探索(2ホップ程度)で済むならRDBでも回るので、規模と探索深度から判断します。

グラフDBを「スケーラビリティ目的」で選ぶ

問題は、グラフDBはクエリの種類(関係性探索)で選ぶものなのに、スケーラビリティを目当てに選んでしまうことです。Neo4j Causal Clusterは読み込みのスケールアウトには対応しますが、書き込みスループット重視なら他のモデルが有利です。

対策は、「グラフをスキャンするか・関係性を辿るか」で選ぶことです。スループット目当てなら別モデルにします。

スキーマレスを「自由度」と勘違いする

問題は、ドキュメントDBはスキーマレスでも、運用上はアプリ側に暗黙のスキーマがあることです。揃えずに運用すると、フィールド名のゆらぎ、型の混在(数値と文字列)、欠損フィールドの取り扱い齟齬で詰まります。

対策は、アプリ側で型・必須項目・値の制約を明文化することです(MongoDBならJSON Schemaバリデーション、Couchbase / Cosmos DBならORM層やアプリのバリデーションで補う)。

性能ベンチマークを真に受ける

問題は、NoSQLはデータモデル・API・チューニング前提が異なるため、ブログ記事の数値比較に再現性がないことです。著者が得意なプロダクトが最も速く出ます。

対策は、性能比較は定性的な観点(マルチマスタなら近いDCに書ける、シャーディングがハッシュかレンジか、メモリ使用量の特性など)に絞り、自分のワークロードでベンチを取って確認することです。

早見表

「AWS中心」「Azure中心」のクラウド代替は各ユースケースの本文側で記載しています。早見表ではモデル・プロダクトの第一候補を中心に整理します。

ユースケース第一候補代替・補足
キャッシュ・セッションRedisMemcached
ランキング・タイムラインRedis (Sorted Set)-
レート制限・カウンタRedis (INCR)-
Pub/Sub・メッセージングRedis (Pub/Sub / Streams)Kafka / RabbitMQ
ジョブキューイングRedis (List / Streams)SQS / RabbitMQ / Kafka
IoT時系列CassandraDynamoDB / Cosmos DB / 時系列特化DB
行動ログ・イベントCassandraDynamoDB / Cosmos DB
メッセージング基盤CassandraDynamoDB
Webアプリ半構造データMongoDBDocumentDB / Cosmos DB / Couchbase
EC商品カタログMongoDBDocumentDB / Cosmos DB
ログ集約MongoDBElasticsearch / OpenSearch
業界横断データ集約MongoDB-
高速プロトタイプMongoDB-
詐欺検知・経路・人材マッチングNeo4j-
モバイル同期Couchbase (Lite)Firestore
マルチDCCassandra / CouchbaseDynamoDB Global Tables / Cosmos DB
Hadoopバッチ結果のオンライン提供HBase-

まとめ

NoSQL選定は要件分解 → データモデル選定 → プロダクト選定の3段階で考えます。

  • まずRDB(OLTP)で困っていることがNoSQLで解ける課題かを切り分ける。バッチ集計・大量ローディングはNoSQLの領分ではない
  • 次にクエリパターン・整合性・スケール・データ構造でデータモデルを決める
  • 最後にエコシステム(クラウド・既存運用・モバイル要件・マルチDC要件)でプロダクトを絞る

「とりあえずMongoDB」「とりあえずRedis」ではなく、ユースケースの要件から逆引きで道具を選びます。それで十分に絞れない場合だけ、複数候補のベンチマークと運用コストの比較に進みます。

参考書

タグ: RDB , NoSQL , データベース基礎