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

我想与MongoDB进行速度比较,并运行了一个测试,该测试将获取并打印15条记录从我们庞大的数据库中随机抽取。我为mysql和MongoDB分别运行了约1000次查询,但我很惊讶我没有注意到速度差异很大。也许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;
}
?>
 


评论

我不是DBA,所以这不是评论,也不是答案,但是在MySQL和MongoDB之间进行选择时,速度不应成为主要考虑因素。对于诸如选择无模式与模式(即,数据模式需要多久更改一次)和规模缩放(即,将数据分片以便于一次典型的读取仅需要来自一台服务器的数据的难易程度)之类的事情而言,这更重要。这样。

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

@ImranOmarBukhsh,的确如此。我的观点来自于不建议为更改而更改-而是建议一种可以利用现有技术来提高性能的方法:)

这个问题使我想起了:mongodb-is-web-scale.com

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

#1 楼

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

人们在很大程度上看到了现实世界中MongoDB的性能因为MongoDB允许您以更适合您的工作量的另一种方式进行查询。

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

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

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


对集合进行一次索引查找(假设实体是由id提取的)
检索一个数据库页面的内容(实际的二进制json文档)

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

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


在根上查找一个索引表(再次假设该实体是通过id提取的)
使用聚集索引,我们可以假设根行的值在索引中
20+范围查找(希望在索引上)用于实体的pk值
这些可能不是聚集索引,因此一旦我们弄清了合适的子行是什么,就进行了20多次数据查找。

所以mysql的总数,即使假设所有索引都在内存中(难度更大,因为它们的数量要多20倍)大约是20个范围查找。

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

因此,在此示例中,最终计数大约是20次与MongoDB相比,每个逻辑访问使用MySQL的IO数量更多。

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

评论


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

– ariso
13年1月1日在17:34

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

– Sean Reilly
2013年3月1日21:00

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

– Geo C.
2014年9月9日在21:45



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

–奥德留斯(Audrius Meskauskas)
2014年9月2日在6:20



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

– BHS
2014年9月27日下午5:46

#2 楼

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

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

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

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

评论


您可以分享您的结果吗?

– Imran Omar Bukhsh
2012年4月3日在15:28

是的,结果会很有帮助

–瓦西尔·波波夫(Vasil Popov)
13年6月28日在12:26

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

– Seabizkit
16-2-26在13:27

#3 楼

来源: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)


评论


15分钟插入10,000行?那是一个非常贫乏的MySQL数据库。以我的经验,如果这种操作的持续时间接近1秒,我的电话会因抱怨而亮起。 :)

– Mordechai
15年11月15日在12:31

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

– elipoultorak
15年11月27日在8:58



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

– Iurie Manea
17年1月9日在23:14

我知道这是一个旧线程,但是几年前,我有一个脚本,该脚本将具有加密过程的300,000行导入到台式机的MySQL中-大约花费了5分钟。我建议这个结果集是有缺陷的。

– WizPip
17年5月17日在15:12

任何人相信声称需要花费1.7秒在mysql中插入十行的人都应该从mongo那里痛苦

–约翰·豪格兰德
19年3月20日在21:19

#4 楼

嗯,答案是,您基本上是在测试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();


vs

$db = new AQLDatabase();


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

urghhh。

评论


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

– JSON
2014年12月30日,0:10

不要选择兰特号码。显然,您每次都错过了创建连接。所有问题加起来就是要测试超出预期的东西。

–Gabe Rainbow
2014年12月30日下午6:10

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

– JSON
2014年12月31日23:06

我同意他的基准测试可能会有所不同,但是它反映出与我所见过的其他MySQL vs Mongo基准相同的基本结果。插入时,Mongo通常会更快(对于更简单的插入,它会更快),而选择时,MySQL通常会更快。

– JSON
2014年12月31日23:24



诚然,我太客气了;正是“
”的html字符串连接确实将我“催逼了”。您在测试中不需要漂亮的打印。即使迭代也似乎是php测试,而不是数据库测试。总体而言,AQLDatabase“可能/也许”时刻...更多成分意味着更多未知数。

–Gabe Rainbow
2015年1月9日,0:34

#5 楼

https://github.com/reoxey/benchmark

基准

MySQL和MongoDB在GOLANG1.6和PHP5中的速度比较

系统适用于基准测试:DELL cpu i5第4代1.70Ghz * 4内存4GB GPU内存2GB

RDBMS与NoSQL的INSERT,SELECT,UPDATE,DELETE执行不同行数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版本和存储引擎?

–user2312578
17 Mar 19 '17在12:28



指定MySQL和MongoDB版本很重要。

– Miron
17年8月14日在6:57

不要使用MyISAM。一定要使用成批插入!

–里克·詹姆斯(Rick James)
17年8月14日在16:48

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

–提示
20-2-9在6:31

#6 楼

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


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


#7 楼

老实说,即使MongoDB速度较慢,Mon​​goDB绝对会让我和你的编码更快。...无需担心愚蠢的表列,行或实体的迁移...
使用MongoDB,您只需实例化一个类并保存!

#8 楼

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

评论


您能否提供一些证据或更多细节来支持这一点?

–史蒂夫·威斯布鲁克
13-10-3在20:39

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

–内斯塔斯(Ernestas)
2014年3月11日19:15

这不是真的。 MongoDB的文件限制为16MD。如果您愿意,MySQL可以有更多功能

–user3480828
2014年3月31日11:10