MySQL vs MongoDB 1000读取

Imr*_*hsh 305 mysql performance mongodb

我对MongoDb非常兴奋并且最近一直在测试它.我在MySQL中有一个名为posts的表,大约有2000万条记录仅在名为"id"的字段上编入索引.

我想比较MongoDB的速度,我运行了一个测试,它将从我们庞大的数据库中随机获取和打印15条记录.我为mysql和MongoDB运行了大约1000次查询,我很惊讶我没有注意到速度上的很多差异.也许MongoDB快了1.1倍.这非常令人失望.有什么我做错了吗?我知道我的测试并不完美,但是当涉及阅读密集的杂务时,MySQL与MongoDb相当.


注意:

  • 我有双核+(2线程)i7 cpu和4GB内存
  • 我在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;
}

?>
Run Code Online (Sandbox Code Playgroud)


用于测试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;
}
?>
Run Code Online (Sandbox Code Playgroud)

Sea*_*lly 620

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多次数据查找.

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

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

因此,对于此示例,与MongoDB相比,每个逻辑访问的最终计数大约是MySQL的20倍.

这就是MongoDB如何在某些用例中提高性能.

  • @ariso:这是通过非规范化进行的优化.它可以提供性能提升.但是,如果你这样做,那么你就会抛弃干净的设计,以及关系数据库的所有功能(更不用说大多数功能)了.它只有在达到列限制时才真正起作用. (91认同)
  • 如果我们只在mysql中放入一个主表怎么办? (39认同)
  • 我想说,20个连接很可能不是最佳数据库模式的最佳查询. (9认同)
  • @SeanReilly你的实例示例(应该用对象编辑,没有面向实体的编程:))无效.就像上面说的那样,你可以序列化一个对象并将其存储在db中并在需要时反序列化(任何形式的序列化).持久化对象的真正威力存在于oodbms而不是documnet db系统中.但我同意每个人都有自己的目的和实力(但你的例子更多地模糊了这个主题的愿景和相关性). (7认同)
  • @SeanReilly我发现你的例子非常有帮助.您可以构建一个特殊的MySQL接口,自动将对象序列化和反序列化为表,并按照mongodb的方式运行.但是,为什么不只是使用专门设计用于这种方式的东西?你对"实体"的使用也是有道理的.关键是您要将数据组织为文档而不是表中的字段.文档是否是以OO语言编写的对象与示例无关. (7认同)
  • @Geo C 这是真的,但是如果不存储映射到对象的重复列,则几乎不可能搜索对象...例如,如果在关系数据库中将一堆用户存储为序列化 json,而我想成为能够根据电子邮件、姓名、年龄等进行查找...我需要一个或多个带有重复信息的附加表来进行查找。其次,您的 json 对象将是半“不可变”的,因为您必须替换整个对象才能更新单个属性...(反序列化-&gt;更改-&gt;序列化-&gt;存储) (3认同)
  • @GeoC.:“实体”一词的使用是合适的——它是 Eric Evans 所著的《领域驱动设计》一书中的术语。http://en.wikipedia.org/wiki/Domain_driven_design#Building_blocks_of_DDD (2认同)

the*_*oid 57

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

但我强烈建议您构建一个真正的负载测试会话,这意味着在同一时间使用JMeter等注入器与10,20或50个用户,这样您就可以真正看到差异(尝试将此代码嵌入到网页JMeter中)可以查询).

我今天刚刚在一台服务器(以及一个简单的集合/表)上完成了它,结果非常有趣且令人惊讶(与MyISAM引擎和InnoDb引擎相比,MongoDb在写入和读取方面确实更快).

这应该是你的测试的一部分:并发和MySQL引擎.然后,数据/架构设计和应用程序需求当然是超出响应时间的巨大要求.让我知道当你得到结果时,我也需要对此有所了解!

  • 你能分享一下你的成绩吗? (39认同)
  • 当然,这只会扩展...如果它是苹果苹果,就像他们在本主题的其余部分一直在说的那样.因此,如果它在avg上执行x,现在从多个源模拟,请解释为什么mongo会更快.也就是说,为了协议的缘故,为了单个请求,mysql的平均速度更快...为什么mongo现在会变得更快?我发现这不是很科学.我说这个测试是有效的..但是如果你把苹果和苹果比较,就像主题的其他部分所解释的那样差异将是多么巨大. (3认同)

小智 33

资料来源:https://github.com/webcaetano/mongo-mysql

10行

mysql insert: 1702ms
mysql select: 11ms

mongo insert: 47ms
mongo select: 12ms
Run Code Online (Sandbox Code Playgroud)

100行

mysql insert: 8171ms
mysql select: 10ms

mongo insert: 167ms
mongo select: 60ms
Run Code Online (Sandbox Code Playgroud)

1000行

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

mongo insert: 1013ms
mongo select: 677ms
Run Code Online (Sandbox Code Playgroud)

10.000行

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

mongo insert: 9956ms (9.95 seconds)
mongo select: 4539ms (4.539 seconds)
Run Code Online (Sandbox Code Playgroud)

  • 插入10,000行15分钟?这是一个非常贫乏的MySQL数据库.根据我的经验,如果这样的操作持续时间接近1秒,我的手机会因投诉而亮起.:) (81认同)
  • 10.000行15分钟?你键入了每一行?=)))) (70认同)
  • 几点:1)Mysql需要进行优化和配置,有很多不同的方法可以插入大量数据,并且正确完成它可以占用15分钟的0.1%,见[本页](http:/例如,/ dbahire.com/testing-the-fastest-way-to-import-a-table-into-mysql-and-some-interesting-5-7-performance-results/).2)MongoDB不会立即将数据写入磁盘,这就是为什么它"看起来"更快,但如果你的计算机崩溃,数据就会丢失.3)MySQL中的读取速度要快得多 (13认同)
  • 对于 10,000 行 - 删除索引、插入、重新索引 (3认同)
  • 我知道这是一个旧线程,但几年前我有一个脚本将 300,000 行带有加密过程的行导入桌面上的 MySQL - 大约需要 5 分钟。我建议这个结果集是有缺陷的。 (2认同)
  • 这些“INSERT”是批量的吗? (2认同)
  • 调查[来源](https://github.com/webcaetano/mongo-mysql/blob/master/mysql.js)我想我已经找到了问题的根源。对于 15K 中的每一个,这是 1 次 INSERT 到 mysql 服务器的完整往返,这对作者来说非常天真。除了实习中最糟糕的代码之外,我从来没有遇到过这样的事情。 (2认同)
  • @AndreFigueiredo 在现实世界中,如果您拥有所有数据,您将进行批处理,但出于分析目的,一次一个更好地模拟多个用户进行更小的插入。但是,引擎和索引有很大的不同。 (2认同)
  • 任何人相信声称需要花费1.7秒将十行插入mysql的人都应该得到mongo的痛苦 (2认同)

Gab*_*bow 19

男人,,,答案是你基本上测试PHP而不是数据库.

无论是否注释掉印刷品,都不要费心去迭代结果.有一大块时间.

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

而另一块人正在花费大量的兰特数字.

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

    }
    return $numbers;
}
Run Code Online (Sandbox Code Playgroud)

然后是一个主要的差异b/w内爆和进入.

最后这里发生了什么.看起来每次都创建一个连接,因此它测试连接时间加上查询时间.

$m = new Mongo();
Run Code Online (Sandbox Code Playgroud)

VS

$db = new AQLDatabase();
Run Code Online (Sandbox Code Playgroud)

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

urghhh.

  • 当然,编码实践在任何情况下都会产生很大的不同,但这并不是特定于任何类型的语言,API或扩展.在启动计时器之前生成随机数会产生影响,但是进程内的大部分时间无疑是来自数据库事务.随机数生成是微不足道的,SQL和NoSQL数据库则不是. (4认同)
  • 不要选择兰特数字。显然你每次都错过了创建连接。所有问题加起来都会导致测试超出预期。 (2认同)
  • 不,不要错过它.MySQL不会关闭连接,直到脚本完成,除非调用mysqli_close().否则,重复调用mysqli_connect()只会从当前资源表中提取现有的mysql资源,而不是提交新的连接过程.我不确定AQLDatabase对象是什么,但如果它使用mysql lib(它可能会这样做),它将具有相同的行为.MongoDB扩展使用连接池,因此在脚本中多次创建mongodb"连接"时会发生同样的基本事情. (2认同)

Reo*_*xey 17

https://github.com/reoxey/benchmark

基准

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

系统用于基准测试:DELL cpu i5第四代1.70Ghz*4 ram 4GB GPU内存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
Run Code Online (Sandbox Code Playgroud)

  • myisam不是innodb,还有哪个mongodb版本和存储引擎? (4认同)
  • 指定 MySQL 和 MongoDB 版本很重要。 (3认同)
  • MySQL 在插入查询中比 Mongodb 更快?!直到 mysql 需要准备列和重新关系之前,这似乎不是真的。mysql select 比 mongodb select 快,但是在插入查询中,mongo 更快 (3认同)
  • 不要使用 MyISAM。请使用批量插入! (2认同)

Jas*_*ngs 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数据库作为替代方案,同时考虑到由于数据库规模较大而导致的存储和内存大小成本。