MySQL与MongoDB 1000读取

我对MongoDb非常兴奋,最近一直在testing它。 我在MySQL中有一个名为posts的表,其中只有一个名为'id'的字段索引了大约2000万条logging。

我想比较MongoDB的速度,我运行了一个testing,从我们庞大的数据库中随机获取并打印15条logging。 我为mysql和MongoDB运行了大约1000次的查询,我感到惊讶,我没有注意到速度有很大的不同。 也许MongoDB速度是1.1倍。 这非常令人失望。 有什么我做错了吗? 我知道我的testing并不完美,但是当涉及到阅读密集的杂事时,MySQL与MongoDb是一致的。

注意:

  • 我有双核+(2线程)I7 CPU和4GB RAM
  • 我在MySQL上有20个分区,每个分区有100万条logging

用于testingMongoDB的示例代码

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

用于testingMySQL的示例代码

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

MongoDB不是神奇的更快。 如果你存储了相同的数据,基本上以相同的方式组织起来,并以完全相同的方式访问它,那么你真的不应该期望你的结果会有很大的不同。 毕竟,MySQL和MongoDB都是GPL,所以如果Mongo有一些更好的IO代码,那么MySQL团队可以将它整合到代码库中。

人们看到真实世界的MongoDB性能很大程度上是因为MongoDB允许您以不同的方式查询,而这种方式对您的工作负载更为明智。

例如,考虑一个以规范化的方式持续了大量关于复杂实体的信息的devise。 这可以很容易地使用MySQL(或任何关系数据库)中的数十个表以常规forms存储数据,并且需要许多索引来确保表之间的关系完整性。

现在考虑与文档存储相同的devise。 如果所有这些相关的表都从属于主表(并且通常是),那么您可能可以对数据进行build模,从而将整个实体存储在单个文档中。 在MongoDB中,您可以将其作为单个文档存储在一个集合中。 这是MongoDB开始实现卓越性能的地方。

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

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

所以一个B树查找,和一个二进制页面读取。 Log(n)+ 1 IOs。 如果索引可以完全驻留在内存中,那么1 IO。

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

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

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

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

因此,对于这个例子,与MongoDB相比,每个逻辑访问最终的计数是使用MySQL的IO的20倍

这就是MongoDB 在某些用例中可以提升性能的方法

你有并发,即同时用户? 如果你直接运行1000次查询,只用一个线程,几乎没有区别。 太容易这些引擎:)

但我强烈build议你build立一个真正的负载testing会话,这意味着使用一个像JMeter一样的注入器,在同一时间有10个,20个或50个用户,所以你可以真正看到一个区别(尝试在网页中embedded这个代码JMeter可以查询)。

我今天在一台服务器(和一个简单的集合/表)上做了,结果是相当有趣和令人惊讶的(与MyISAM引擎和InnoDb引擎相比,MongoDb写入和读取速度更快)。

这真的应该是你的testing的一部分:并发和MySQL引擎。 那么,数据/模式devise和应用程序的需求当然是超出响应时间的巨大需求。 让我知道,当你得到的结果,我也需要投入这个!

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

人,,,答案是,你基本上是testingPHP而不是数据库。

不要打扰重复的结果,无论是否注释出版。 有一段时间。

  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内爆。

最后是这里发生了什么。 看起来像每次创build一个连接,因此它testing的连接时间加上查询时间。

 $m = new Mongo(); 

VS

 $db = new AQLDatabase(); 

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

urghhh。

https://github.com/reoxey/benchmark

基准

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

系统用于基准testing:戴尔cpu i5第四代1.70Ghz * 4 ram 4GB GPU ram 2GB

用于INSERT,SELECT,UPDATE,DELETE的RDBMS与NoSQL的速度比较执行不同的行数10,100,1000,10000,100000,1000000

用来执行的语言是:PHP5和谷歌最快的语言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 

下面是使用MySQL和Mongo探索RDBMS和NoSQL 的一些研究 ,结论与@Sean Reilly的回应是一致的。 总之,好处来自于devise,而不是一些原始的速度差异。 结论在第35-36页:

RDBMS与NoSQL:性能和缩放比较

该项目testing,分析和比较了两种数据库types的性能和可伸缩性。 所做的实验包括运行不同数量和types的查询,其中一些比其他更复杂,以分析数据库如何随着负载的增加而进行缩放。 在这种情况下,最重要的因素是用于MongoDB的查询types能够更快地处理更复杂的查询,这主要是因为其更简单的模式而牺牲了数据复制,这意味着NoSQL数据库可能包含大量的重复数据。 尽pipe可以使用从RDBMS直接迁移的模式,但是这样可以消除MongoDB底层数据表示子文档的优势,允许在组合表时使用较less的数据库查询。 尽pipe在这些复杂的查询中,MongoDB对MySQL的性能有所提高,但是当基准使用嵌套SELECT对MySQL查询进行类似于MongoDB复杂查询的MySQLbuild模时,MySQL的性能performance最好,尽pipe在连接数较多的情况下,它们的行为相似。 基准查询的最后一种types是包含两个JOINS和一个子查询的复杂查询,显示了MongoDB对MySQL的优势,因为它使用了子文档。 这个好处是以导致数据库大小增加的数据重复为代价的。 如果这样的查询在应用程序中是典型的,那么考虑NoSQL数据库作为替代品是很重要的,同时考虑到由于较大的数据库大小而导致的存储和内存大小的成本。

在单服务器上,由于table / doc大小为1 GB到20 GB,MongoDb在读和写上都不会比mysql MyISAM更快。
在多节点群集上的并行减less时,MonoDB的速度会更快,而Mysql不能水平扩展。