(レポート) MongoDB勉強会:MongoDB v3.4新機能と遅いときの切り分け方法
こんにちは、菊池です。
12/14(水)に開催された、MongoDB勉強会に参加してきましたのでレポートします。
主催はクリエーションライン株式会社様で、以下の2テーマで行われました。
- MongoDB v3.4 の新機能について:クリエーションライン株式会社 CSO 鈴木 逸平 様
- MongoDBが遅いときの切り分け方法:渡部 徹太郎 様
レポート
開催にあたって、本勉強会の位置付け/主旨の説明がありました。
- MongoDBが普及してきた。
- すでにMongoDBを知っている人向けにトリッキーな所に着目してイベントを開催したい。
- 入門レベル/概要的な内容は、MongoDBだけではなく他のNOSQLを含めて比較する内容でやるべき。
MongoDB v3.4 の新機能について
- 2016/6にMongoDB World開催
- 2016/11、MongoDB Europe 16が開催
- キーノートからみれる傾向/方向性/MongoDBの立ち位置
- ユーザー事例
- バイドゥ(百度)100個のMongoDB利用アプリ・1000ノードを運用
- BARCLAYS(金融)フロントのデータストア・リアルタイム性のあるモバイルアプリ
- NOW TV(コンテンツ配信)
- 6月のMongoDB Europeのキーノートと同じで進歩があまり見られない
- MongoDB Atlas登場
- 3.4年内リリースのアナウンス
- 追加機能の数は多いがインパクトあるものがない
- あえていうならAggregationフレームワーク・BIコネクタ
- 3.4以降のロードマップが出ていない
新機能
- マルチモデルサポート
- 裾野を広げる使い方が増えている印象
- データモデルの拡大
- サードパーティストレージエンジンサポート
ビッグデータ・分析関連の機能拡張
- グラフ処理
- 多面的ナビゲーション
- 照合順序/多言語のソートに対応
- 小数点データ処理
- 高度な分析:アグリゲーションパイプライン
- BIコネクタ
- Tableau連携
- Aggregationと組み合わせてTableauに渡すデータを簡略化する
- Hadoop/Sparkコネクタ
- データレイクとしての活用
ミッションクリティカル向け機能拡張
- ゾーンサポート(地域をキーにしたシャーディング)
- Elastic Cluster
- クラスタ間のデータ圧縮
- Tunableコンシステンシー(データ一貫性)
- LDAP
- Read Only ビュー
- ARMサポート
新世代ツール
- MongoDB コンパス
- クエリと性能の最適化ツール
- 地理情報データ分析
- CRUD可能
- 性能の可視化
- インデックス分析
- OpsManager
- 精度向上
新機能の傾向
- 欧米はすでに大量のデータがあるケースが多い -> BIやアグリゲーション拡張のニーズが大きい
- 日本はHdoopやクラウドが先行しているところへ普及 -> フロントのデータストアとして使う
MongoDBが遅いときの切り分け方法
導入
- MongoDBはRDBより早いか?
- ケースによる
- 提供している機能セットが違う
- 結局はIOをどれだけ減らせるか
- シャーディング
- ボトルネックを分散させられているか(データの分散だけではだめ)
- クエリを分散させる
- 方向性はRDBにも通じることなので、RDBの基本を学ぶこと
性能問題との向き合い方
- 問題の明確化
- 本当にDBが遅いのか
- どのクエリが遅いのか
- 何を改善したいのか(レスポンスorスループット)
- 根本原因の特定
- リソース
- 非効率な処理 ロック/フェッチ
- 根本原因の解消
- 3000クエリ/秒は単体(シャーディングなし)でいける
- まずは単体構成での性能を限界まであげる(8割のケースはこれでOK)
- できるだけシャーディングはしない(シャーディングすると運用負荷が4倍になる)
- よくある間違い
- CPU使用率が高い -> リソースを使えているのはいいこと
- メモリ使用量が高い -> IOが発生してなければ問題ない
- 完璧なチューニングとは全てのリソースを100%利用できている状態
- データベースの限界性能を引き出すこと
問題の明確化
- 本当にMongoDBが遅いのか?
- 各レイヤーの処理時間を計測すること
- これができてないことが多い
- 何が遅い?Read or Write or 集計
- どのの指標が遅い?
- レスポンス -> スロークエリ
- スループット -> mongotop/mongostat
- スロークエリログ
- プロファイラを有効にする
- db.setPrifileLevel(1)
- mongotop/mongostatは運用中、ログとして出力させてもいい
- クラウドマネージャ(OpsManager)を使う
- 監視項目を設計しなくていい
根本原因の特定
- 結論は2つ
- なんらかのハードリソースがボトルネック
- CPU
- メモリ/IO
- NW
- ボトルネックがない(余裕がある)
- アプリのフェッチが細かすぎる
- 書き込みロック待ち
- CPU
- アグリゲーション
- 一部のコアのみ使ってないか
- ロードアベレージがコア数以上になっていないか
- コア数/クロック上げるしかない
- NW
- APに大量のデータを返している
- Oplog転送量が想定以上に肥大化
- NWを太くする
- 射影して減らす
- multi update/remove、配列の$pop、$pull などは大量にOplogをだす
- IO
- キャッシュ溢れ
- MMAPの場合、ページフォルト
- WiredTigerの場合:"byte read into cache"が物理メモリを超えて増えている
- インデックスと実行計画、hint句
- キャッシュ増やす
- 処理が非効率
- 書き込み
- ロック待ち
- バッチインサートしてない
- WriteConcern
- WiredTigerの同時実行クエリは最大128に制限
- 読み込み
- フェッチ
- 同時実行128制限
- 書き込み
MMAPv1とWiredTigerのアーキテクチャとIOボトルネック
- MMAPv1
- メモリ要求はOSへmmap()
- 起動直後は空
- MongoDBはメモリの状態を知らない
- Writeが遅い理由
- DB単位ロック(3.0はコレクション単位)
- ジャーナルなしでは60秒ごとに非同期書き込み = ジャーナルなしだと60秒のデータロストリスクがある
- ジャーナルがあると100msでフラッシュ
- Readが遅い理由
- 起動直後
- インデックスが大きすぎる
- OSに空きメモリがない
- メモリには全ドキュメントが乗る -> ドキュメントがでかいと非効率
- ブロックサイズがドキュメントに対して大きいと無駄
- IOネックで書き込みが遅い時
- インデックス
- ジャーナル/データ/ログはディスクを分ける
- ドキュメントが大きくて物理移動が発生している(フラグメント)
- WiredTiger
- MongoDB自身でメモリ管理
- 更新は新しいドキュメントを挿入して、ポインタを書き換え(MVCC/CAS)
- ロックがない
- 移動がない
- フラグメントがない
- インデックスとデータが別ファイルに
- データ圧縮(メモリは圧縮しない)
- 読み込むとrootツリー形成
- 書き込みジャーナルは50msごとに圧縮してフラッシュ
- 内部トランザクション
- MVCCでコミットされるまでは古いドキュメントが見える
- チェックポイントは60秒またはジャーナルが2GBを超えるとき
- 読みが遅い
- MMAPより複雑なので遅い場合がある
- WiredTigerにメモリを割り当てすぎて、OSのページキャッシュに使えていない場合もある
- DiskIO が多い場合に非効率になる(ページキャッシュは圧縮がきく)
- OOMになる可能性あり
- Read中心ならばMMAPv1もあり
- read/write比率で線引き
QA
- WiredTigerでのメモリの設定の目安は? -> ワークロードによる
- 推奨ファイルシステム -> xfs。ext3は非推奨
- バリデーションのエラーをアプリでハンドリング可能か -> エラーがそっけないので難しい
まとめ
入門ではなく中級者向けの勉強会ということで、参加者も実際にMongoDBを利用している方が多く、非常に濃い内容でした。特に、Ver. 3.0以降で採用されたWiredTigerの内部実装・動作についてはドキュメントも少ないのでとても参考になりました。
今後も、実際に使用しているユーザ向けにコアな内容の勉強会を継続開催されるとのことでしたので、期待したいと思います。