MySQL vs MongoDB 1000读取


320

我对MongoDb感到非常兴奋,并且最近对其进行了测试。我在MySQL中有一个名为posts的表,其中大约2000万条记录仅在名为“ id”的字段上建立索引。

我想将速度与MongoDB进行比较,然后运行了一个测试,该测试将从我们的大型数据库中随机获取并打印15条记录。我为mysql和MongoDB分别运行了约1,000次查询,但我惊讶地发现我在速度上并没有太大差异。也许MongoDB快1.1倍。真令人失望。我做错什么了吗?我知道我的测试并不完美,但是在阅读繁琐的杂物方面,MySQL与MongoDb相当。


注意:

  • 我有双核+(2个线程)i7 cpu和4GB ram
  • 我在MySQL上有20个分区,每个分区有1百万条记录

用于测试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之间进行选择时,速度不应成为主要考虑因素。对于选择而言,诸如无模式与模式(即,数据模式需要多久更改一次)以及规模缩放(即,将数据分片以便于一次典型的读取仅需要来自一台服务器的数据的难易程度)之类的事情更为重要。像这样。
rossdavidh 2012年

17
如何更快地阅读?它从机械设备读取。与MySQL相同。这取决于设备本身的速度,您不能通过代码使用一些怪异的魔术来突破硬件限制。
NB 2012年

7
这个问题让我想起了:mongodb-is-web-scale.com
oligofren 2014年

13
人们误以为自己会和一个或另一个一起去。您的厨房将需要微波炉和烤箱。您只是不能说我只会使用一个或另一个。两个系统的用例不同。如果您的应用程序的一部分需要ACID,则使用RDBMS,如果不关心一致性和约束,并且您的实体可以作为一个整体存储(集合),则使用MongoDB。您最终将使用混合系统,关键是要决定在哪里存储什么。
Teoman shipahi 2015年

Answers:


644

MongoDB并不是神奇的更快。如果您以相同的方式存储相同的数据,并以完全相同的方式进行组织,并且以完全相同的方式访问它们,那么您真的不应该期望结果会大相径庭。毕竟,MySQL和MongoDB都是GPL,因此,如果Mongo中包含一些神奇的更好的IO代码,则MySQL团队可以将其合并到他们的代码库中。

人们看到现实世界中的MongoDB性能主要是因为MongoDB允许您以更适合您的工作量的不同方式查询。

例如,考虑一种设计,该设计以规范化方式保留了有关复杂实体的许多信息。这可以轻松地使用MySQL(或任何关系数据库)中的数十个表以标准形式存储数据,并需要许多索引来确保表之间的关系完整性。

现在考虑与文档存储相同的设计。如果所有这些相关表都从属于主表(并且经常属于主表),则您可能能够对数据建模,以便将整个实体存储在单个文档中。在MongoDB中,您可以将其作为单个文档存储在单个集合中。这是MongoDB开始提供卓越性能的地方。

在MongoDB中,要检索整个实体,您必须执行:

  • 在集合上进行一次索引查找(假设通过id获取实体)
  • 检索一个数据库页面的内容(实际的二进制json文档)

因此,进行b树查找,并读取二进制页面。Log(n)+ 1个IO 如果索引可以完全驻留在内存中,则为1 IO。

在具有20个表的MySQL中,您必须执行:

  • 在根表上进行一次索引查找(同样,假设该实体是通过id获取的)
  • 对于聚集索引,我们可以假设根行的值在索引中
  • 实体pk值的20多次范围查找(希望在索引上)
  • 这些可能不是聚簇索引,因此一旦我们确定了合适的子行是什么,就进行了20多个相同的数据查找。

因此,即使假设所有索引都在内存中(由于索引数量增加了20倍,所以比较困难),mysql的总数仍约为20个范围查找。

这些范围查找可能由随机IO组成-不同的表肯定会驻留在磁盘上的不同位置,并且同一实体在同一表的同一范围内的不同行可能不连续(取决于该实体的状态)更新等)。

因此,对于此示例,与MongoDB相比,每个逻辑访问的最终IO数比MySQL多20倍

这是MongoDB 在某些用例中可以提高性能的方式。


43
如果我们只在mysql中放一张主表怎么办?
ariso

98
@ariso:这是通过非规范化进行的优化。它可以提高性能。但是,如果这样做,则将浪费干净的设计以及关系数据库的所有功能(更不用说大多数功能了)。只有在达到列限制之前,它才真正起作用。
肖恩·赖利2013年

7
@SeanReilly您的实体示例(应使用对象进行编辑,没有面向实体的编程:))无效。就像ariso所说的那样,您可以序列化一个对象并将其存储在db中,并在需要时反序列化(任何形式的序列化)。持久对象的真正力量在于oodbms而非documnet db系统中。但是我同意,每个人都有自己的目的和优势(但是您的示例模糊了该主题的视野和相关性)。
Geo C.

9
我想说,20个联接可能不是对最佳数据库模式的最佳查询。
Audrius Meskauskas 2014年

8
@SeanReilly我发现您的示例非常有帮助。您可以为MySQL建立一个特殊的接口,该接口自动将对象序列化和反序列化到表中,并表现出mongodb的行为。但是,为什么不仅仅使用专门设计用于这种方式的东西呢?您对“实体”的使用也是有道理的。关键是要把数据组织成文档而不是表中的字段。文档是否是用OO语言组成的对象与示例无关。
BHS

57

您是否有并发性,即并发用户?如果仅使用一个线程直接运行1000次查询,则几乎没有区别。这些引擎太简单了:)

但是,我强烈建议您建立一个真正的负载测试会话,这意味着在同一时间使用具有10、20或50个用户的注入器(例如JMeter),以便您能真正看到差异(尝试将此代码嵌入JMeter网页中可以查询)。

今天,我只是在一台服务器(和一个简单的集合/表)上完成此操作,结果非常有趣且令人惊讶(与MyISAM引擎和InnoDb引擎相比,MongoDb的读写速度确实更快)。

这确实应该是测试的一部分:并发和MySQL引擎。然后,数据/架构设计和应用程序需求当然是巨大的需求,超出了响应时间。让我知道您获得结果时,我也需要有关此的输入!


42
您可以分享您的结果吗?
Imran Omar Bukhsh 2012年

1
是的,对此的结果将非常有帮助
Vasil Popov

3
当然,如果只是像苹果公司一样,在本主题的其余部分中一直这样说的话,这只会扩大规模。因此,如果它在avg上执行x,现在可以从多个来源进行模拟,请解释为什么mongo会更快。也就是说,为了达成共识,我们只能说mysql对于单个请求在avg上运行速度更快...为什么mongo现在对多个请求变得更快?我觉得这不是很科学。我是说测试是有效的..但是不确定如何将苹果与其他主题类似的苹果进行比较,差异有多大。
Seabizkit '16

36

资料来源: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
15分钟插入10,000行?那是一个非常贫乏的MySQL数据库。以我的经验,如果这种操作的持续时间接近1秒,我的电话会因抱怨而亮起。:)
Mordechai 2015年

1
Xtreme Biker看看链接。我用其他设置发布了来自其他人的测试。
user2081518 2015年

14
需要注意的几点:1)需要优化和配置Mysql,有很多不同的方法可以插入大量数据,正确执行可能需要15分钟的0.1%,例如,请参见此页面。2)MongoDB不会立即将数据写入磁盘,这就是为什么它“看起来”更快的原因,但是如果您的计算机崩溃,则数据将丢失。3)在MySQL中阅读速度更快
elipoultorak

81
10.000行15分钟?您输入了每一行?=))))
Iurie Manea

6
任何人相信声称要在mysql中插入十行仅需要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;
}

然后黑白内爆和内爆之间存在重大差异。

最后是这里发生的事情。看起来每次都创建一个连接,因此它测试了连接时间加上查询时间。

$m = new Mongo();

$db = new AQLDatabase();

因此对于剥离爵士乐的基础查询,您的速度提高101%可能会快1000%。

恩。


4
自然,在任何情况下编码实践都可以带来很大的不同,但这并非特定于任何类型的语言,api或扩展。在启动计时器之前生成随机数会有所不同,但是毫无疑问,该过程中的大部分时间都来自数据库事务。随机数的生成很简单,而SQL和NoSQL数据库则不然。
JSON 2014年

1
不要选择兰特号码。显然,您每次都错过了创建连接。所有问题加起来就是测试了意料之外的事情。
Gabe Rainbow

2
不,没有错过。除非调用mysqli_close(),否则在脚本完成之前,MySQL不会关闭连接。否则,重复调用mysqli_connect()只会从当前资源表中拉出现有的mysql资源,而不是提交新的连接过程。我不确定AQLDatabase对象是什么,但是如果它使用mysql lib(可能这样做),则会具有相同的行为。MongoDB扩展使用连接池,因此在脚本中多次创建mongodb“连接”时,也会发生相同的基本情况。
JSON

我同意他的基准测试可以做得不同,但是它反映出与我所见过的其他MySQL vs 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

针对执行不同行数10,100,1000,10000,100000,1000000的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

myisam不是innodb,还有哪个mongodb版本和存储引擎?

1
指定MySQL和MongoDB版本很重要。
米龙

1
不要使用MyISAM。一定要使用成批插入!
瑞克·詹姆斯

MySQL在插入查询方面比Mongodb更快?在mysql需要准备列和关系之前,这似乎并不正确。MySQL的选择比快的mongodb选择,但是在插入查询,蒙戈更快
Exind

6

这是一项使用MySQL vs Mongo探索RDBMS vs NoSQL 的小研究,结论与@Sean Reilly的回应一致。简而言之,好处来自设计,而不是一些原始的速度差异。结论在第35-36页:

RDBMS与NoSQL:性能和扩展比较

该项目测试,分析和比较了两种数据库类型的性能和可伸缩性。完成的实验包括运行不同数量和类型的查询,其中一些查询比其他查询更复杂,以便分析数据库如何随着增加的负载进行扩展。在这种情况下,最重要的因素是所使用的查询类型,因为MongoDB可以更快地处理更复杂的查询,这主要是由于它的简单模式牺牲了数据重复,这意味着NoSQL数据库可能包含大量数据重复。尽管可以使用直接从RDBMS迁移的模式,但这将消除MongoDB子文档的基础数据表示形式的优点,即在合并表时可以对数据库使用较少的查询。尽管在这些复杂查询中MongoDB在性能上优于MySQL,但当基准测试通过嵌套嵌套SELECT与MongoDB复杂查询建模时,MySQL表现最佳,尽管在连接数量较多时,两者的行为相似。基准测试的最后一种查询类型是包含两个JOINS和一个子查询的复杂查询,这表明MongoDB由于使用子文档而具有优于MySQL的优势。此优势是以数据复制为代价的,该数据复制会导致数据库大小增加。如果此类查询在应用程序中很常见,则重要的是考虑NoSQL数据库作为替代方案,同时考虑到由于数据库较大而导致的存储和内存大小成本。


-6

在单服务器上,给定的表/文档大小在1 GB到20 GB之间,MongoDb在读写方面都不会比mysql MyISAM快。
在Mysql无法水平扩展的多节点群集上,MonoDB在Parallel Reduce上会更快。


5
您能否提供一些证据或更多细节来支持这一点?
史蒂夫·威斯布鲁克

无法水平缩放?那NDB呢?DRBD支持MySQL?
Ernestas 2014年

这不是真的。MongoDB的文件限制为16MD。如果您愿意,MySQL可以有更多功能
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.