dragon image みちのぶのねぐら

リレーショナルデータベースは遅い

Update: 2013-03-10

もう10年以上前のことになりますが、昔々米国からコンピュータというものが日本にやってきたときに、カタカナ(たぶん、いわゆる半角の)を使えるようにしたという大先輩のお話を聞く機会がありました。その中で「リレーショナルデータベースはなぜこんなに遅いのか。アーキテクチャを間違っているとしか思えない。」とおっしゃっていました。

その通り、遅いです。今でも遅いです。今はやりの NoSQL と比べての話ではありません ( ちなみに NoSQL の中には、使い方によっては MySQL より遅いものものあるようです ) 。普通に遅いです。世の中のリレーショナルデータベースを使ったシステムの大半は、インデックスをしっかり効かせた OLTP 用途なのだろうと思いますが、それとは少し違うことをすればすぐに性能上の問題が出るはずです。なにしろ、普通にベタファイルを読み書きするより遅いのですから。

どのくらい遅いか自分の MacBook Pro で改めて試してみました。 SSD じゃない遅いマシンです。測定には以前 インデックスの有無と INSERT の所要時間 ( MySQL ) で使った MySQL のデータを利用します。

まず、 INSERT ... SELECT... で 100万行をまるごとテーブルからテーブルにコピーしてみます。一行ずつ INSERT してないので、 SQL のパースなどのオーバーヘッドはほとんどない状態だと思います。

date +%s ; echo "insert into t3 select * from t1" | mysql -uroot -pxxxxxxxx test  ; date +%s

79秒です。

次に、同じデータをファイルに書き出してみます。

date +%s ; echo "select * from t1" | mysql -uroot -``pxxxxxxxx` `test > t1.txt ; date +%s

76秒です。ファイルサイズは 1GB くらいになりました。

ファイルからファイルにコピーしてみます。

date +%s ; cat t1.txt > t2.txt ; date +%s

57秒です。

出力先を /dev/null にしてみます。まず、 MySQL から。少しでもオーバーヘッドを減らすために、全くヒットしない WHERE 条件を付けます。テーブルフルスキャンするだけ、なにも結果を返さない、という処理になるはずです。

date +%s ; echo "select * from t3 where c6 = 'x'" | mysql -uroot -pxxxxxxxx test > /dev/null ; date +%s

23秒です。何度か繰り返すと、キャッシュが効くのか 3秒くらいになります。終わってから気がついたのですが、何も出力しないから /dev/null にする必要はなかったな。

ファイルから。

date +%s ; cat t2.txt > /dev/null ; date +%s

24秒です。こちらも繰り返してみましたが 1秒以内になるようです。

OS が管理するファイルシステムのキャッシュの恩恵は、 MySQL も平等に受けてますよね?