本文へジャンプします。

ニフティクラウドでMongoDBは使えるか?

>>>>>> こちらはゲストによる寄稿記事になります

<2011/06/01 17:30 追記–

※ MongoDB JPの管理人 @doryokujin さんが指摘の記事を書いてくださいました
>>
「ニフティクラウドでMongoDBは使えるか?」を読んで、僕なりの考察を書いてみた

出来る限り勉強はいたしましたが、考察の足りないところ、明確にしておくべきところが不足しておりました。ユーザの方に誤解を与えてしまうことお詫びいたします。
是非、あわせてお読みください。

–2011/06/01 17:30>
 

 こんにちは、ニフティのモリフジです。

分析などを行っているうえでMongoDBを調べています。
寄稿記事として、こちらのブログで執筆させていただきました。

 今回、「ニフクラ上でMongoDBを動作させたときのパフォーマンス」についてご説明したいと思います。

■MongoDBとは

  MongoDBはMySQLのようなRDB、memcachedのようなKVS、HBase/CassandraのようなDHTとは毛色の違う、「document-oriented」なデータベースです。

注:今回の記事は、必要に応じてMongoDBの紹介や、利用方法に少し触れますが、インストールの手順やその他設定についての記事ではありません。

Document-orientedって?

 特徴としては公式ドキュメントでは下記4点があげられています   

  • ドキュメント(オブジェクト)がプログラム言語のデータ型にうまく対応している 
  • 埋め込みドキュメントと配列によって、ジョインの必要性が低減している 
  • スキーマの進化を容易にする動的型付け(スキーマレス) 
  • 高いパフォーマンスと、容易なスケーラビリティを確保するためにジョインや複数ドキュメントのトランザクションは無い
  •  私見も交え、端的にいってしまうと

    メリット
  • スキーマレスなので機能拡張の要件や、開発中・運用初期のAdhocなスキーマチューニングなどには「超」柔軟に対応できます
  • 面倒なこと考える前にひとつのドキュメントに詰め込めばいいです。ブログだったらエントリーにコメントも全部!
  • デメリット
  • トランザクションが無いために課金などのシステムにも使えません
  • 面倒だったら突っ込めっていったけど、ドキュメントあたり4MB(v1.8以降から16MB)しか使えない 
  • 埋め込みと正規化のハザマで苦しむことになる
  •  という、ある種の男らしい決断を必要とする反面、男らしく調整しながら突き進むときには最適なデータベースです。

    ■ShardingとReplica

      上記4番目の特徴としてあげた「容易なスケーラビリティ」を実現するのが「Sharding」と「Replica」機能です。これらの機能を利用する・しないによって書き込み性能・読み込み性能、次に紹介するmapReduceの性能が変わってきます。

    Sharding

      ドキュメントデータを複数のサーバで分割して保持する機能をShardingといいます。指定したドキュメントのキー(例えばユーザリストであれば名前など)をA-Dまではサーバ1で、E-Oまでをサーバ2、P-Zまでをサーバ3で、という具合に分割して保持します。これにより、書込性能・検索性能の向上を実現しています。

    Replica

      ドキュメントを保持しているサーバが破損した場合に備え、また、読み込み性能をバランスすることを目的として、保持しているデータを複数台のサーバにコピー(replication=複製)して保持しておく機能です。 

    ■MapReduce

      MongoDBには、もう一つ非常に大きな武器があります。それがMapReduceという機能です。   Google BigTableやHadoopといったキーワードを耳にした方ならなじみのあるキーワードで、MapReduceを利用される方は年々増加の一途をたどっていますが、一般的にはまだまだ認知されていないかと思います。

     MapReduceは巨大なデータの分析・解析という用途において非常に強力な力を発揮します。下記のような処理の一連の流れ全体で「MapReduce」と呼び、大きなデータを分割し、小さな単位で処理し、処理して縮めた結果を分析することで、巨大なデータの解析を可能にしています。

  • 巨大なデータを何らかの方法で切り分け、いくつかのブロックに分割します
  • ブロックごとに処理を行いKeyとValueのペアとして出力します(Map) 
  • ブロックごとに処理されたKeyとValueのペアを、Keyごとに再分割します(Shuffle & Sort)
  • Keyごとに収集して処理を行います(Reduce)
  • Keyごとに収集されたデータに対して統計的な処理を行います(Finalize)
  •  この機能は、当然、1台のマシンで行うときには、あまり意味がなく、Shardingを実現し、複数台のマシンがあるときに、より有効に機能します。分割されたブロックはそれぞれ異なるサーバでMap処理することが可能なためI/Oを節約し、Shardingで分割したサーバの台数分のCPUやMemoryで処理することが出来るからです。
     

     少し、MongoDBで実現できる機能について少しお話しておきます。

    対話shell

      MongoDBをインストール後、コンソールから$MONGO_HOME/bin/mongoを実行してみてください。対話shellが起動します。

    
    $ mongo
    > show dbs
    admin
    config
    mydb
    > use mydb
    switched to db mydb
    > show collections
    logs
    system.indexes
    >

     こんな感じで

  • db一覧を取得する(show dbs)
  • 利用するdbを変更する(use)
  • collection一覧を取得する(show collections)
  • などを行うことが出来ます。

     また、困ったときには

    
    > help
    db.help()                    help on db methods
    db.mycoll.help()             help on collection methods
    (略)
    > db.help()
    DB methods:
      db.addUser(username, password[, readOnly=false])
      db.auth(username, password)
    (略)
    > db.logs.help()
    DBCollection help
      db.logs.find().help() - show DBCursor help
      db.logs.count()
    > rs.help()
      rs.status()                     { replSetGetStatus : 1 } checks repl set status
      rs.initiate()                   { replSetInitiate : null } initiates set with default settings > db.listCommands() addShard: no-lock adminOnly  slaveOk   add a new shard to the system applyOps: no-lock   no help defined

     などと、対話shellでのhelpも充実しています。   

    豊富なコマンド群

     上記の対話shellを起動するmongo、サーバ起動のためのmongod、shardingのクライアントとして機能するmongos以外にも多くのコマンドが存在します。

    mongoimport
     データのバッチ投入に便利です。データベース/コレクションを指定し、json以外にもtsv, csvのデータも投入でき、また、その際のfield定義なども指定することが容易に出来ます。また、通常のファイルだけではなく標準入力も受けるため、非常に使い勝手のよいツールになっています。

    
    $ tail -f /var/log/access.log | perl ./filter.pl | mongoimport -d mydb -c mycol -f timestamp,host,path,ua,ip

    mongoexport
     データベース/コレクションを指定して、バックアップ目的などでデータの出力が可能です。JSONとcsvを選択できます。また、指定した条件にマッチしたドキュメントのを指定したフィールドだけ取得することも可能です。

    mongodump
     データベースをバックアップ目的でdumpすることが可能です(データはbinaryで保存されます)。指定したドキュメントだけを取得することが出来ます。

    mongorestore
     データベースのリストア目的でdumpしたデータから復旧します。

    ■Benchmark

      下記のような条件およびプロセスでベンチマークを行い、プロセス完了までの時間を計測しました。

    データ

      twitterのtweetを1.4GB (delete含めて707,259tweet)   

    条件 
  • shardingの有無(1台=無 vs. 3台) 
  • stripingの有無(有 vs. 無) 
  • ニフティクラウドスペック(mini vs large16)
  •   注:stripingについてはニフティクラウドにMySQLは載せられるのか?パフォーマンス大検証!をご覧ください

    <2011/06/01 17:30追記>

    shardのケースについて

    shardkeyにはtweetの増加の少ないものとして「userのid」、時間経過に伴う増加の多いものとして「tweetのid」を設定しました。
    また、indexは貼らずに検証しました(意図的に貼らなかったのですが、張ったケースを比較すべきでした。)

    プロセス 
    mongoimport
     おそらく日々のバッチ投入、またはログからのアクション更新のペースの頻繁なリテラシの高い企業ではリアルタイムデータ投入が行われるでしょう。このときにデータの投入がそもそももたるようでは困ります。したがってデータ投入はIOやshardingを測定する上で重要な項目です。

    find
     コレクションからデータを取得するコマンドです。MongoDBの場合は、ドキュメントを縦横無尽に条件付けてフィルタリングができるのでこの性能も無視できない重要な性能です。

  • 1条件 find({source:’web’})       
  • ネスト条件 find({‘user.lang’:’ja’})       
  • 否定 find({‘geo’:{$ne:null}})       
  • サイズ find({‘entities.hashtags:{$size:2}})       
  • 比較 find({‘retweet_cnt’:{$gt:1}})   
  • mapreduce
     MongoDBを十二分に活用するのであれば、避けられないコマンドです。簡単な解析に利用することが出来ます(簡単、と書きましたがかなり使えます)。

  • 単純なグループ集計(source集計)
  • 単純なグループ集計(5分ごとのtweet数集計)       
  • 2条件のグループ集計(1時間当たり・1人当たりのtweet数集計)       
  • 少し複雑な集計(1時間当たりのhashtag集計)       
  • 少し複雑な集計(共起するhashtag集計)   
  • 結果

      実際に行った結果は下記の通りです(単位=ms, n=5)。

    スペック mini large16
    sharding
    striping
    mongoimport 549.201 520.438 630.101 690.042 259.671 104.757 263.050 193.803
    find 38.378 42.293 13.618 14.998 1.044 1.030 1.124 1.132
    mapreduce 226.64 229.46 107.39 106.85 52.53 52.10 26.08 26.08

    考察

    全体

      全体的にざっくりと見ると、当然といえば当然ですが、VMのスペックがimport/find/mapreduceに大きなパフォーマンスの差に影響を及ぼしています。

     また、IO性能に関わるstripingに関しては、import、特にlarge16以外ではほとんど意味のある効果を発揮していませんでした。これはminiの場合はIOよりもmemory/cpuがボトルネックになっているためだと考えられます。

     データサイズが1.4GBであるため、mini(memory=512MB)においてはfindやmapreduceにおいてIO性能の及ぼす影響が強いと予想していましたが、ほとんど見られませんでした。これは今後追求していければと思っています。

    mongoimport

     上記と重複しますが、スペックにおける影響が非常に強く、また、次に、large16のときにstripingの影響が出ていました。このimport処理では書き込み性能に影響が出るため、shardingの影響を予測していましたが、shardingによる性能の改善は見られないばかりか、1台で行った場合よりも劣化するという結果でした。

     この結果は、mongosまたはconfigサーバがボトルネックとなりうるという要因が予測されます。今後、例えばmongosを分割し、それぞれに対して同時にimportを行い、全体としてのパフォーマンスの改善が見られるかを検討する必要があるかと思います。

    find

        IO性能に関わるstripingはほぼ、findにおいては影響を見せませんでした。またshardingによるfindの性能は、miniでは、およそ2倍?3倍程度の改善を示していましたが、large16ではほとんど効果が見られませんでした。同時に、stripingも影響があまり見られませんでした。

     今回の程度のデータサイズであれば、cpu/memory性能が十分に高ければ分散させてIO性能を稼ぐことにあまり意義が無いと考えられます。

    mapreduce

     今回、一番ベンチマークを取った甲斐があるプロセスでした。stripingについては性能にほとんど影響が見られませんでしたが、shardingの効果がよく出ており、簡単とはいえ集計や計算がcpu/memory依存で行われ、mapreduceを複数台で実現することの意味が見出せたものと考えられます。

      今回、すべてのデータについては、分散はほとんど見られなかったこともあり、ざっくりとした考察だけを行っていますが、いかがでしたでしょうか。実際に使う上でshardingを適切に配置し「Largeシリーズ」を使っていただければ。「Largeシリーズ」を使っていただければ、性能がスケールすることも含め、比較的性能的にもよいパフォーマンスが得られたのではないかと思っております。

     なにより、VMが苦手なIOにあまり依存しない、という結果が出たということは、従来のRDBと比べ、利用シーンを選びはしますがニフティクラウドを利用するベネフィットがあるのではないでしょうか。
     

    <2011/06/01 17:30追記>

    • find系のクエリについてshardキーの有無の検証

       
      指摘されたとおりでやるべきでした。@doryokujinさんの記事をご参照ください。
       

    • sharding環境の有無でmongoimportに差が出なかったのは恐らくshardKeyの問題ではないでしょうか。前述しましたが、 shardingは事前に設定したshardKeyに従ってデータを各shardに分割しています。例えばこのshardKeyの値が "_id" を始めとした時間軸に対して増加するキーであった場合には、連続して挿入されるデータは分散されずに同じchunk、つまり同じshardに入ってしまいます。この場合にはshardingしていながら、実際にはシングルサーバーへ書き込みを行っているのと同じ、さらにはmongosサーバーを介することによってシングルよりも無駄なステップを消費しています。今回の結果の原因は、status_idをshardKeyとして使用しているような場合にはこれによるものと考えられそうです。

       
      途中の条件のところにも記載しましたが、今回はuser_idもkeyとしてセットしているため、分散は行われていると考えています。
      そのこともあり、シングルサーバーではないかと思っております(確認しようと思ったのですが、VMがなくなっていました><) 本来の、ボトルネックがどこにあったのかは、追検証できればと思っております。
       

    • このようにMongoDBのmapreduceの特性を理解せずに高スペックマシンの方が高速に動作すると思い込んで毎月数十万を無駄する可能性があります。

       
      普段の開発では意識しているのですが、社員であること・モニター利用であることもあり、ご指摘の通り、費用対効果のことを失念していました。是非、御利用は計画的によろしくお願いいたします。
       

    ニフティクラウド 導入相談窓口
    ニフティクラウド 無料セミナー

    閉じる

    閉じる

    クラウドブログ編集部

    クラウドブログ編集部

    ニフティクラウド ユーザーブログ編集部のアカウントです。 編集部からのお知らせや、レギュラーライター以外のゲストによる寄稿記事を掲載していきます。

    浜中 慶

    浜中 慶

    1980年、神奈川県生まれ。2003年ニフティ入社。 ポータルサイト開発を中心に、音楽配信サービス、CGMサービスなど様々なプロジェクトに企画/デザイン/システム担当として参加。現在は@niftyのポータルサービス向けコンテンツ管理システムの企画/開発/運用を担当。

    吉田 雄哉

    吉田 雄哉

    株式会社co-meetingの創業メンバー。「取締役&External- facing Technologist」と名乗り新しいIT技術を広く伝える活動とWebアプリケーション開発を行う毎日。パッケージベンダーでのSaaS立上げ・製造業の情報システム部門で企画やPM・受託開発と従事してきたため、ベンダーサイドとユーザサイド の両方の視点を持ち合わせる。

    石田 健亮

    石田 健亮

    株式会社ドリーム・アーツで小売事業者向けSaaS「Shopらん」を企画、開発。メインの仕事はプログラマーだがサーバー管理や営業もこなすユーティリティプレイヤー。最近好きな事はパフォーマンスチューニング。特に並列化プログラミングがマイブーム。キライなことはデータセンターでの作業。騒音と乾燥が弱点。ニフティクラウドでデータセンターに行く必要が無くなったことが本当の利点だ と思っている。

    五月女 雄一

    五月女 雄一

    ニフティでは「インフラを守る簡単な様で奥が深いお仕事」をしています。 夢はインフラの気持ちが読めるエンジニアになること。

    わたなべ かずひろ

    わたなべ かずひろ

    専門学校卒業後、ソフトウェア開発会社で電力系統制御システムの開発に従事。その後、CD-ROM等マルチメディア系PCソフトの開発を経て、1998年フリーランスに。 2000年8月に株式会社イーツーの設立に参画。携帯を含む様々なWeb系のシステム開発に携わる。現在はiPhone/Androidアプリなどの開発も手がけている。

    市角

    市角

    ニフティクラウドのコントロールパネル設計・開発をメインに、たまにインフラの運用やお手伝いもやっていたりします。コントロールパネルや新機能の活用方法、アイデアなどを中心に書いていく予定です。

    仲山 昌宏

    仲山 昌宏

    歌って踊れるインフラエンジニア兼、PHPもRubyもJavaも書くPerl使い。 物理サーバの運用に飽きて、フルラックに格安サーバ詰めて自宅プライベートクラウドを構築中。 今年は個人的には分散処理を攻めていきます。

    猪飼 賢広

    猪飼 賢広

    1984年、愛知県名古屋市生まれ。大学は福島県にある某大学。2008年ニフティに入社。 開発系部署に配属後、主に各種テーマサイト開発のシステム面調整、開発進行管理役などとして参加。 現在もPC・ガラケーサイトの開発まわりを担当。インフラまわりを触る案件にも携わっており、日々修行中。 好きな芸人はなかやまきんに君とレイザーラモンRG。

    久江 裕之

    久江 裕之

    ニフティクラウドのインフラ運用、OS提供の仕事をしています。 新しいOSやイメージが出る時にこのブログでご紹介いたします。入社5年目。一流のインフラエンジニアを目指して日々勉強中。

    竹内 豪

    竹内 豪

    ニフティクラウド エンジニア

    山口

    山口

    ニフティクラウドの基盤設計、新サービス/アライアンス/インフラ企画、その他雑用全般を担当しています。 クラウドに欲しい機能や、こんなふうに使ってほしいという想いが共有できれば良いですね。

    芳中 隆幸

    芳中 隆幸

    ニフティクラウドの開発、運用を担当しています。

    酒井 浩平

    酒井 浩平

    ニフティクラウドの中にいます。 ネットワークまわりの運用・開発や自動化などに取り組んでいます。 すべてのエンジニアを幸せにすることを目指しています。

    higebu

    higebu

    ニフティクラウド IaaSのエンジニアです。 ネットワーク、DRサービス with VMware vCloud® Air™ Technology辺りの担当をしています。

    武田

    武田

    ニフティクラウドの開発・運用を担当しています。 各種機能の内容についてなどで執筆させていただく予定です。

    森藤 大地

    森藤 大地

    データに関する仕事が好きです。

    宮原徹

    宮原徹

    日本仮想化技術株式会社 代表取締役社長兼CEO。仮想化技術に関するコンサルタントとして長年活動しており、特にベンチマークテストによる性能評価を得意としている。

    荒谷翔

    荒谷翔

    株式会社はてなでMackerelのセールスデベロッパーとして勤務しています

    東條 望

    東條 望

    2014年にニフティへ中途入社。 入社後から現在まで、ニフティクラウドのサービス企画・開発を担当しています。 各サービスの紹介を執筆させていただく予定です。