MongoDBとMySqlの書き込み速度がどのくらい違うのか、確かめてみた。
その結果、MongoDBの方がMySqlにくらべて約3倍ほど早いことがわかった。
計測結果
1レコード以下のような情報をMongoDBとMySqlにそれぞれ100万件書き込み、その時間を計測します。
_id:5c3b3328c9b636c95173f72a
name:"テスター0"
adress:"東京都新宿区AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0"
str2:"文字列AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0"
age:0
int1:1
int2:2
int3:3
int4:4
update_time:2019-01-13 12:46:32.708
結果は以下の通り。
■MongoDBの書き込み時間
100万件書き込みに掛かった時間・・・2m14.881981654s
■MySqlの書き込み時間
100万件書き込みに掛かった時間・・・5m55.303855555s
実験の結果、MongoDBの方が、MySqlに比べて3倍早いことがわかりました。
どのようにしてMongoDBとMySqlの書き込み速度を確かめたのか
検証環境
検証に使ったPCはMacBook Proです。
具体的なスペックは以下のとおりです。
PC:MacBook Pro (13-inch, 2017, Four Thunderbolt 3 Ports)
CPU:3.1 GHz Intel Core i5
メモリ:8 GB
検証方法
実際に100万件のデータをMongoDB、MySqlそれぞれに書き込んで計測する。
データの書き込みは、Go言語でデータをインサートするプログラムを作成しました。
実際のソースコードは、GitHubに公開しているので、確認したい方は以下をクリック。
MongoDBに100万件のデータをinsertする
https://github.com/jshirius/golang_tools/blob/master/mongo_insert_tester.go
MySqlに100万件のデータをinsertする
https://github.com/jshirius/golang_tools/blob/master/mysql_insert_tester.go
MySqlのテーブル定義は以下のとおりです。
CREATE TABLE `t_persons` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL COMMENT '名前',
`adress` varchar(45) DEFAULT NULL COMMENT '住所',
`str2` text COMMENT 'str2',
`age` int(11) NOT NULL DEFAULT '0',
`int1` int(11) NOT NULL DEFAULT '0',
`int2` int(11) NOT NULL DEFAULT '0',
`int3` int(11) NOT NULL DEFAULT '0',
`int4` int(11) NOT NULL DEFAULT '0',
`update_time` datetime DEFAULT NULL,
`del` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
上記の実験の結果、
MongoDBの書き込み時間・・・2m14.881981654
MySqlの書き込み時間・・・5m55.303855555
になりました。
結局の所、MongoDB、Mysqlのどっちを使ったほうがよいの?
MongoDBとMysqlにはそれぞれ、長所・短所があります。どちらかを使うかは、システムの要件によって決まります。最近は、1つのシステムでも書き込み・更新が多い部分(主にログ)はMongoDB、整合性を重視する部分(主に在庫管理) Mysqlと2つのDBを使い分ける使うケースがあります。
MongoDBにしたほうがよいケース
・書き込みリクエストが多い
・ある程度の整合性を合わせなくても良いケース
・ログを書き込むケース(お金があるならばGoogleのBigQueryの方がおすすめ)
・一つのテーブルで処理を終えることができる(joinを使わない)
※MongoDBにはJoin、トランザクションの機能がない。
■EX
ユーザが行動する毎に発生するログをリアルタイムに書き込む必要がある場面では、MongoDBがよいでしょう。
また、書き込みが多いのに、整合性を合わせる必要があるケースを考えてみます。
RPGゲームでアイテムの購入処理を考えてみます。
アイテムの購入処理:
(1)所持アイテムにアイテムAを追加(insert発生)
(2)お金をアイテムA購入額分減らす(更新発生)
このようなケースは、(1)(2)のどちらも成立する必要があります。MySqlではトランザクションを発生させて処理させますが、MongoDBではトランザクションを使うことができません。(1)(2)どちらかでエラーが起きると整合性が取れなくなります。
この様な場合は、エラーが起きてもユーザーに不利益にならないように設計して、エラーが起きてもよいようにします。今回の場合は(1)が成功したら(2)を実行します。(2)で失敗してお金を減らなくてもユーザにはアイテムが付与できるので、ユーザーから不満が来ることはほぼ無しです。逆に、(1)がエラーでアイテムが付与されていないのに(2)でお金だけ減るケースになってしまうとユーザーからクレームが来てしまいます。
Mysqlを使ったほうがよい
・金融システム(実際はオラクルDBが使われるケースがほとんど)
・join、トランザクションの処理が必要になるケース
・在庫管理システムのように、複数人が1つのレコードを参照、更新するケース。
・複数のレコードで整合性を合わせるケース
EX
在庫管理のように販売する商品数(在庫数)が決まっていて、在庫数以上の商品を売ることができないケース。このようなケースは、整合性を合わせる必要があるのでMongoDBでは不向きと言えます。
読み込み速度はどうなっているの?
読み込み速度についても調べてみました。
検証方法は、MongoDBとMySqlのそれぞれで1万件のデータを読み込みます。
読み込み速度は、Go言語からデータ読み込みの処理時間です。
■処理結果
MongoDBの読み込み時間・・・70.194257ms
MySqlの読み込み時間・・・23.294257ms
MongoDBの方が、3倍も遅いという意外な結果になった。
しかし、MongoDBの読み込み方にボトルネックがあるのかもしれません。
コンソールから
「db.people.find({age:{$gte:10000,$lt:20000}})」で1万件取ろうとしたら一瞬だった。
Goのライブラリー側で何かしらの悪さをしている?
現時点では、MongoDB本体が遅いのか不明である。indexなどのデータの設定の仕方が間違えている可能性があるため、引き続き調査していきます。
まとめ
MongoDBとMysqlにはそれぞれ、長所・短所があることがわかりました。どっちを使うかは、目的によって違ってきます。