MySQL 与 MongoDB 1000 次读取

标签 mysql performance mongodb

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

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

?>


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

最佳答案

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

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

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

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

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

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

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

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

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

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

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

因此,对于本示例,与 MongoDB 相比,MySQL 每次逻辑访问的 IO 大约增加了 20 倍

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

关于MySQL 与 MongoDB 1000 次读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9702643/

相关文章:

mysql - 如何比较两个表中的数据并显示一张表中的数据

mysql - SQL Group By 和两列计数

c++ - 循环效率 - C++

python - 设置 Beeware : I cannot create my JAR support file within my activated venv

php - 检查是否安装了 MongoDB PHP 驱动程序

javascript - 如何在mongodb中加入两个表并插入数组

mongodb - 排序聚合 addToSet 结果

MySQL 不按索引更新

mysql - WebSQL 中表与其自身的一对多关系

java - java中管道模式的实现