MySQLとMongoDB 1000の読み取り


321

私はMongoDbに非常に興奮しており、最近それをテストしています。MySQLにpostと呼ばれるテーブルがあり、 'id'というフィールドでのみ約2,000万のレコードにインデックスが付けられました。

MongoDBと速度を比較したかったので、巨大なデータベースからランダムに15レコードを取得して印刷するテストを実行しました。mysqlとMongoDBに対してそれぞれ約1,000回クエリを実行しましたが、速度に大きな違いはないことに驚いています。たぶんMongoDBは1.1倍高速です。それは非常に残念です。私が間違っていることはありますか?私のテストは完璧ではありませんが、集中的な雑用の読み取りに関しては、MySQLはMongoDbと同等です。


注意:

  • デュアルコア+(2スレッド)i7 cpuおよび4GB ram
  • MySQLに20のパーティションがあり、それぞれ100万レコード

MongoDBのテストに使用されるサンプルコード

<?php
function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}
$time_taken = 0;
$tries = 100;
// connect
$time_start = microtime_float();

for($i=1;$i<=$tries;$i++)
{
    $m = new Mongo();
    $db = $m->swalif;
    $cursor = $db->posts->find(array('id' => array('$in' => get_15_random_numbers())));
    foreach ($cursor as $obj)
    {
        //echo $obj["thread_title"] . "<br><Br>";
    }
}

$time_end = microtime_float();
$time_taken = $time_taken + ($time_end - $time_start);
echo $time_taken;

function get_15_random_numbers()
{
    $numbers = array();
    for($i=1;$i<=15;$i++)
    {
        $numbers[] = mt_rand(1, 20000000) ;

    }
    return $numbers;
}

?>


MySQLをテストするためのサンプルコード

<?php
function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}
$BASE_PATH = "../src/";
include_once($BASE_PATH  . "classes/forumdb.php");

$time_taken = 0;
$tries = 100;
$time_start = microtime_float();
for($i=1;$i<=$tries;$i++)
{
    $db = new AQLDatabase();
    $sql = "select * from posts_really_big where id in (".implode(',',get_15_random_numbers()).")";
    $result = $db->executeSQL($sql);
    while ($row = mysql_fetch_array($result) )
    {
        //echo $row["thread_title"] . "<br><Br>";
    }
}
$time_end = microtime_float();
$time_taken = $time_taken + ($time_end - $time_start);
echo $time_taken;

function get_15_random_numbers()
{
    $numbers = array();
    for($i=1;$i<=15;$i++)
    {
        $numbers[] = mt_rand(1, 20000000);

    }
    return $numbers;
}
?>

11
実際の時間は何ですか?
阿部ペトリロ

30
私はDBAではないので、これは回答ではなくコメントですが、MySQLとMongoDBのどちらを選択するかについては、速度を主な考慮事項とすべきではありません。スキーマレスとスキーマ(つまり、データスキーマを変更する必要がある頻度)やサイズのスケーリング(つまり、一般的な読み取りで1つのサーバーからのデータのみが必要になるようにデータをシャーディングするのがいかに簡単か)などは、選択肢にとってより重要です。このような。
rossdavidh 2012年

17
読書速度を上げるにはどうすればよいですか?機械装置から読み取ります。MySQLと同じ。それはデバイス自体の速度に依存します。ハードウェアの限界を突破するためにコードを介して奇妙な魔法を使うことはできません。
NB

7
この質問は私にこれを思い出させます:mongodb-is-web-scale.com
オリゴフレン

13
人々は自分たちが一緒に行くような気分だと誤解しています。キッチンには電子レンジとオーブンの両方が必要です。私がどちらか一方だけを使用するとは言えません。両方のシステムのユースケースは異なります。アプリの一部にACIDが必要な場合は、RDBMSを使用します。一貫性と制約を気にせず、エンティティをすべて1つのコレクション(コレクション)として保存できる場合は、MongoDBを使用します。最終的にはハイブリッドシステムを使用することになります。重要なポイントは、何をどこに保存するかを決定することです。
Teoman Shipahi 2015年

回答:


647

MongoDBは驚くほど高速ではありません。同じデータを保存し、基本的に同じ方法で整理し、まったく同じ方法でアクセスする場合、結果が大きく異なるとは思わないでください。結局のところ、MySQLとMongoDBはどちらもGPLであるため、Mongoに魔法のように優れたIOコードが含まれている場合、MySQLチームはそれをコードベースに組み込むことができます。

MongoDBでは、ワークロードにより敏感な別の方法でクエリを実行できるため、人々は実際にMongoDBのパフォーマンスを実感しています。

たとえば、複雑なエンティティに関する多くの情報を正規化された方法で保持する設計を考えてみます。これは、MySQL(または任意のリレーショナルデータベース)の数十のテーブルを簡単に使用してデータを通常の形式で格納し、テーブル間の関係の整合性を保証するために多くのインデックスが必要になります。

次に、ドキュメントストアを使用した同じ設計について考えます。これらすべての関連テーブルがメインテーブルに従属している場合(それらは多くの場合そうです)、エンティティ全体が単一のドキュメントに格納されるようにデータをモデル化できる場合があります。MongoDBでは、これを単一のドキュメントとして単一のコレクションに格納できます。これは、MongoDBが優れたパフォーマンスを可能にするところから始まります。

MongoDBでは、エンティティ全体を取得するには、以下を実行する必要があります。

  • コレクションに対する1つのインデックスルックアップ(エンティティがIDによってフェッチされると想定)
  • 1つのデータベースページ(実際のバイナリjsonドキュメント)のコンテンツを取得する

つまり、Bツリールックアップとバイナリページの読み取りです。Log(n)+ 1 IO。インデックスが完全にメモリに常駐できる場合、1 IO。

20のテーブルを持つMySQLでは、以下を実行する必要があります。

  • ルートテーブルでの1つのインデックスルックアップ(ここでも、エンティティがIDでフェッチされると仮定)
  • クラスタ化インデックスでは、ルート行の値がインデックスにあると想定できます
  • エンティティのpk値の20以上の範囲ルックアップ(できればインデックス上)
  • これらはおそらくクラスター化インデックスではないため、適切な子行が何であるかがわかったら、同じ20以上のデータ検索を行います。

したがって、mysqlの合計は、すべてのインデックスがメモリ内にあると仮定した場合でも(インデックスが20倍あるため困難です)、約20の範囲ルックアップになります。

これらの範囲ルックアップは、ランダムIOで構成される可能性があります。異なるテーブルはディスク上の異なる場所に確実に存在し、エンティティの同じテーブル内の同じ範囲内の異なる行が連続していない可能性があります(エンティティがどのように行われたかによって異なります)更新など)。

したがって、この例では、最終的な集計は、MongoDBと比較して、論理アクセスあたりのMySQLでのIOの約20倍です。

これは、MongoDBが一部のユースケースでパフォーマンス向上させる方法です。


43
mysqlにメインテーブルを1つだけ配置するとどうなるでしょうか。
ariso

99
@ariso:これは非正規化による最適化です。パフォーマンスを向上させることができます。ただし、これを行うと、クリーンなデザインと、リレーショナルデータベースのすべての機能(ほとんどの機能は言うまでもありません)が破棄されます。そしてそれはあなたが列の制限に達するまで実際にのみ機能します。
Sean Reilly、2013年

7
@SeanReillyエンティティを含む例(オブジェクトで編集する必要があります。エンティティ指向のプログラミングはありません:))は無効です。arisoが言ったように、オブジェクトをシリアライズしてdbに格納し、必要に応じてデシリアライズできます(シリアライズの任意の形式)。永続オブジェクトの真の力は、documnet dbシステムではなくoodbmsに保持されています。しかし、それぞれに独自の目的と強みがあることに同意します(ただし、この例では、このトピックのビジョンと関連性がわかりにくくなっています)。
ジオC.

9
私が言うには、20の結合は、おそらくこれらが可能な最良のデータベーススキーマに対する最良のクエリではありません。
Audrius Meskauskas 2014

8
@SeanReilly私はあなたの例がとても役に立ちました。オブジェクトを自動的にテーブルにシリアル化および逆シリアル化し、mongodbと同じように動作するMySQLへの特別なインターフェイスを構築できます。しかし、そのように使用するために特別に設計されたものを使用しないのはなぜですか?また、「エンティティ」の使用には意味があります。重要なのは、データをテーブルのフィールドとしてではなくドキュメントとして整理することです。ドキュメントがオブジェクト指向言語で構成されたオブジェクトであるかどうかは、例とは関係ありません。
BHS 2014

57

同時実行、つまり同時ユーザーはありますか?スレッドを1つだけ使用して、1000回だけクエリをそのまま実行すると、ほとんど違いがありません。これらのエンジンには簡単すぎる:)

ただし、真の負荷テストセッションを構築することを強くお勧めします。つまり、JMeterなどのインジェクターを同時に10、20、または50ユーザーで使用して、違いを実際に確認できます(このコードをWebページJMeterに埋め込んでみてください)照会できます)。

私は今日、単一のサーバー(および単純なコレクション/テーブル)でそれを実行しただけで、結果は非常に興味深く、驚くべきものでした(MongoDbは、MyISAMエンジンやInnoDbエンジンと比較して、書き込みと読み取りが本当に高速でした)。

これは実際にテストの一部である必要があります:同時実行性とMySQLエンジン。次に、データ/スキーマの設計とアプリケーションのニーズはもちろん、応答時間を超えて大きな要件になります。結果が出たらお知らせください。これについての入力も必要です。


42
結果を共有できますか?
Imran Omar Bukhsh

1
はい、その結果は非常に役に立ちます
Vasil Popov '28

3
確かにこれはスケールするだけです...もしそれがこのトピックの残りの部分で彼らが言っているようなAppleからAppleであるなら。したがって、平均でxを実行する場合は、複数のソースからシミュレートし、mongoの方が高速になる理由を説明してください。つまり、同意のために、mysqlが単一のリクエストで平均よりも高速であったとしましょう...なぜmongoは複数のリクエストでより高速になるのですか?これは非常に科学的だとは思いません。テストは有効だと言っていますが、残りのトピックで説明しているように、アップルとアップルを比較した場合、その違いがどの程度大きいかはわかりません。
Seabizkit 2016

35

ソース:https : //github.com/webcaetano/mongo-mysql

10行

mysql insert: 1702ms
mysql select: 11ms

mongo insert: 47ms
mongo select: 12ms

100行

mysql insert: 8171ms
mysql select: 10ms

mongo insert: 167ms
mongo select: 60ms

1000行

mysql insert: 94813ms (1.58 minutes)
mysql select: 13ms

mongo insert: 1013ms
mongo select: 677ms

10.000行

mysql insert: 924695ms (15.41 minutes)
mysql select: 144ms

mongo insert: 9956ms (9.95 seconds)
mongo select: 4539ms (4.539 seconds)

91
10,000行を挿入する15分?これは非常に貧弱なMySQLデータベースです。私の経験では、そのような操作の継続時間が1秒に近づくと、私の電話が点灯して不満が出てきます。:)
Mordechai 2015年

1
Xtreme Bikerがリンクを見てください。他の人からのテストを他の設定で投稿しました。
user2081518 2015年

14
いくつかの点:1)Mysqlは適切に最適化および構成する必要があります。大量のデータを挿入するにはさまざまな方法があり、適切に実行すると15分のうち0.1%かかります。たとえば、このページを参照してください。2)MongoDBはデータをすぐにディスクに書き込まないため、「見た目」が速くなりますが、コンピューターがクラッシュするとデータは失われます。3)MySQLでは読み取りがはるかに高速です
elipoultorak 2015年

81
10.000行で15分?各行を入力しましたか?=))))
Iurie Manea 2017年

7
mysqlに10行を挿入するのに1.7秒かかるという主張を信じる人は誰でも、mongoから受ける苦痛に値する
John Haugeland

20

答えは、データベースではなく基本的にPHPをテストしているということです。

プリントをコメント化するかどうかにかかわらず、結果を繰り返し処理する必要はありません。時間のチャンクがあります。

   foreach ($cursor as $obj)
    {
        //echo $obj["thread_title"] . "<br><Br>";
    }

もう一方のチャンクは、ランド番号の束を集めるのに費やしています。

function get_15_random_numbers()
{
    $numbers = array();
    for($i=1;$i<=15;$i++)
    {
        $numbers[] = mt_rand(1, 20000000) ;

    }
    return $numbers;
}

次に、b / wの内外で大きな違いがあります。

そして最後にここで何が起こっているのか。毎回接続を作成するように見えるため、接続時間とクエリ時間をテストします。

$m = new Mongo();

$db = new AQLDatabase();

そのため、ジャズが取り除かれた基になるクエリでは、101%高速になる可能性があります。

うわぁ。


4
当然のことながら、コーディングの実践はどのような状況でも大きな違いを生む可能性がありますが、これは特定の種類の言語、API、拡張機能に固有のものではありません。タイマーを開始する前に乱数を生成すると違いが生じますが、プロセス内のほとんどの時間はデータベーストランザクションによるものです。乱数の生成は簡単ですが、SQLおよびNoSQLデータベースはそうではありません。
JSON

1
ランド番号を選択しないでください。毎回、接続の作成に失敗しました。すべての問題は、意図したもの以外のものをテストすることになります。
Gabe Rainbow

2
いいえ、見逃していません。MySQLは、mysqli_close()が呼び出されない限り、スクリプトが終了するまで接続を閉じません。そうでない場合、mysqli_connect()への繰り返し呼び出しは、新しい接続手順にコミットするのではなく、現在のリソーステーブルから既存のmysqlリソースのみをプルします。AQLDatabaseオブジェクトが何であるかは正確にはわかりませんが、mysql libを使用している場合(可能性があります)、同じ動作になります。MongoDB拡張機能は接続プーリングを使用するため、スクリプトでmongodbの「接続」を複数回作成すると、同じ基本的なことが起こります。
JSONは2014

彼のベンチマークは異なる方法で行われた可能性があることにも同意しますが、これは私が見た他のMySQLとMongoのベンチと同じ基本的な結果を反映しています。通常、Mongoは挿入時に高速になり(より単純な挿入の場合ははるかに高速)、MySQLは通常、選択時に高速になります。
JSONは2014

確かに、私はあまりにもばかげていました。「<br>」のhtml文字列連結が本当に私を「悩ませた」のです。テストできれいな印刷をする必要はありません。それを繰り返しても、phpのテストのようであり、データベースのテストではないようです。全体として、そのAQLDatabaseは「おそらく/おそらく」の瞬間です...成分が増えると、未知数が増えることを意味します。
Gabe Rainbow

17

https://github.com/reoxey/benchmark

基準

GOLANG1.6とPHP5でのMySQLとMongoDBの速度比較

ベンチマークに使用されたシステム:DELL cpu i5 4th gen 1.70Ghz * 4 ram 4GB GPU ram 2GB

異なる行数を実行するINSERT、SELECT、UPDATE、DELETEのRDBMSとNoSQLの速度比較10,100,1000,10000,100000,1000000

実行に使用される言語は次のとおりです:PHP5&Google最速言語GO 1.6

________________________________________________
GOLANG with MySQL (engine = MyISAM)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
10                      1.195444ms
100                     6.075053ms
1000                    47.439699ms
10000                   483.999809ms
100000                  4.707089053s
1000000                 49.067407174s


            SELECT
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 872.709µs


        SELECT & DISPLAY
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 20.717354746s


            UPDATE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 2.309209968s
100000                  257.411502ms
10000                   26.73954ms
1000                    3.483926ms
100                     915.17µs
10                      650.166µs


            DELETE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 6.065949ms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


________________________________________________
GOLANG with MongoDB
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
10                      2.067094ms
100                     8.841597ms
1000                    106.491732ms
10000                   998.225023ms
100000                  8.98172825s
1000000                 1m 29.63203158s


            SELECT
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 5.251337439s


        FIND & DISPLAY (with index declared)
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 21.540603252s


            UPDATE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1                       1.330954ms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

________________________________________________
PHP5 with MySQL (engine = MyISAM)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
 10                     0.0040680000000001s
 100                    0.011595s
 1000                   0.049718s
 10000                  0.457164s
 100000                 4s
 1000000                42s


            SELECT
------------------------------------------------
num of rows             time taken
------------------------------------------------
 1000000                <1s


            SELECT & DISPLAY
------------------------------------------------
num of rows             time taken
------------------------------------------------
  1000000               20s
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

________________________________________________
PHP5 with MongoDB 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
10                      0.065744s
100                     0.190966s
1000                    0.2163s
10000                   1s
100000                  8s
1000000                 78s


            FIND
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 <1s


            FIND & DISPLAY
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 7s


            UPDATE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 9s

myisamはinnodbではなく、どのmongodbバージョンとストレージエンジンですか?

1
MySQLとMongoDBのバージョンを指定することが重要です。
Miron

1
MyISAMを使用しないでください。バッチ挿入を使用してください!
リックジェームズ

MySQLは挿入クエリでMongodbよりも高速ですか?mysqlが列と関係を準備する必要があるまでは、そうではないようです。選択MySQLの高速化にMongoDBを選択するよりもですが、挿入クエリで、モンゴは高速です
Exind

6

これは MySQLとMongoを使用してRDBMSとNoSQLを調査た小さな研究です。結論は、@ Sean Reillyの応答と一致しています。要するに、利点は設計から得られ、生の速度の違いではありません。35-36ページの結論:

RDBMSとNoSQL:パフォーマンスとスケーリングの比較

このプロジェクトでは、2つのデータベースタイプのパフォーマンスとスケーラビリティをテスト、分析、比較しました。行われた実験には、負荷の増加に伴うデータベースのスケーリングを分析するために、さまざまな数とタイプのクエリの実行が含まれています。この場合の最も重要な要因は、MongoDBがより複雑なクエリをより速く処理できるために使用されるクエリタイプでした。これは、主にデータ複製の犠牲にある単純なスキーマにより、NoSQLデータベースに大量のデータの重複が含まれる可能性があるためです。RDBMSから直接移行したスキーマを使用することもできますが、これにより、MongoDBの基礎となるサブドキュメントのデータ表現の利点がなくなり、テーブルを組み合わせたときにデータベースへのクエリを少なくすることができます。これらの複雑なクエリでMongoDBがMySQLよりもパフォーマンスが向上したにもかかわらず、ネストされたSELECTを使用してベンチマークがMySQLクエリをMongoDB複雑なクエリと同様にモデル化した場合、接続数が多いと2つは同様に動作しましたが、MySQLは最高のパフォーマンスを発揮しました。ベンチマークされた最後のタイプのクエリは、2つのJOINSと1つのサブクエリを含む複雑なクエリで、サブドキュメントを使用しているため、MongoDBがMySQLよりも優れていることを示しています。この利点は、データベースのサイズの増加を引き起こすデータの複製を犠牲にしてもたらされます。このようなクエリがアプリケーションで一般的である場合、より大きなデータベースサイズに起因するストレージとメモリサイズのコストを考慮しながら、代替としてNoSQLデータベースを検討することが重要です。


-6

単一サーバーでは、テーブルとドキュメントのサイズが1 GBから20 GBと小さいため、MongoDbは読み取りと書き込みの両方でmysql MyISAMよりも速くはありません。
MyDBは、Mysqlが水平方向にスケーリングできないマルチノードクラスターのParallel Reduceでより高速になります。


5
それを裏付ける証拠または詳細を提供できますか?
Steve Westbrook

水平方向にスケーリングできませんか?NDBはどうですか?MySQLをサポートするDRBD?
Ernestas 2014年

本当じゃない。MongoDBには16MDドキュメントの制限があります。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.