web-dev-qa-db-ja.com

MySQLとMongoDB 1000の読み取り

私はMongoDbに非常に興奮しており、最近それをテストしています。 MySQLにはpostsという名前のテーブルがあり、約2000万件のレコードが 'id'というフィールドにのみインデックス付けされています。

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


注意:

  • 私はデュアルコア+(2スレッド)i7 CPUと4GBのRAMを持っている
  • MySQLには100万レコードそれぞれ20パーティションあります。

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;
}
?>
287

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

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

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

次に、ドキュメントストアを使用した同じ設計を検討します。これらのすべての関連テーブルがメインテーブルに従属している場合(多くの場合はそうです)、エンティティ全体が1つのドキュメントに格納されるようにデータをモデル化できる場合があります。 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での論理アクセスごとに20回 more IOです。

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

607
Sean Reilly

同時ユーザー、つまり同時ユーザーはいますか。たった1つのスレッドで1000倍のクエリを実行しただけでは、ほとんど違いはありません。これらのエンジンにとっては余りにも簡単:)

ただし、実際の負荷テストセッションを作成することを強くお勧めします。つまり、10、20、50ユーザーのJMeterなどのインジェクタを使用することです。[AT THE SAME TIME Webページ内のコードJMeterが問い合わせることができます)。

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

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

53
theAndroid

ソース: 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)
31
user2081518

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

印刷物をコメントアウトするかどうかにかかわらず、結果の繰り返しを気にする必要はありません。たくさんの時間があります。

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

もう一方のチャンクは、多数のRand番号をまとめるために費やしています。

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();

vs

$db = new AQLDatabase();

そのため、101%速いあなたのジャズの根本的なクエリの1000%速いことがわかるかもしれません。

うーん。

19
Gabe Rainbow

https://github.com/reoxey/benchmark

ベンチマーク

gOLANG1.6とPHP5でのMySQLとMongoDBのスピード比較

ベンチマークに使用されるシステム:Dell CPU i5第4世代1.70GHz * 4ラム4GB GPUラム2GB

INSERT、SELECT、UPDATE、DELETEでRDBMSとNoSQLを比較して異なる行数を実行した場合

実行に使用される言語は次のとおりです。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
14
Reoxey

ここに ちょっとした研究 MySQL対Mongoを使用してRDBMS対NoSQLを調査した、結論は@ Sean Reillyの応答と一致していました。一言で言えば、利点は設計から来るのであり、生の速度差ではありません。 35-36ページの結論:

RDBMSとNoSQL:性能とスケーリングの比較

プロジェクトは、2つのデータベースタイプのパフォーマンスとスケーラビリティをテスト、分析、および比較しました。行われた実験では、データベースが負荷の増大に応じてどのように拡張されたかを分析するために、さまざまな数および種類のクエリを実行しました。この場合の最も重要な要素は、主にデータの重複を犠牲にした単純なスキーマのため、MongoDBがより複雑なクエリをより速く処理できるように使用されるクエリタイプです。 RDBMSから直接移行されたスキーマを使用することができますが、これはMongoDBのサブドキュメントの基礎となるデータ表現の利点を排除します。 これらの複雑なクエリでMongoDBがMySQLに比べてパフォーマンスが向上したにもかかわらず、ベンチマークがネストしたSELECTを使用してMongoDBの複雑なクエリと同様にMySQLクエリをモデル化したとき。 2つのJOINと1つのサブクエリを含む複雑なクエリである最後のベンチマークのクエリでは、サブドキュメントを使用しているためMongoDBがMySQLより優れていることがわかりました。この利点はデータの重複を犠牲にしてデータベースサイズの増加を引き起こします。そのようなクエリがアプリケーションで一般的である場合、より大きいデータベースサイズに起因するストレージおよびメモリサイズのコストを考慮しながら、NoSQLデータベースを代替手段と見なすことが重要です。

4
Jason Hitchings