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 树查找,并读取二进制页面。 Log(n) + 1 个 IO。如果索引可以完全驻留在内存中,则 1 个 IO。

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

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

因此,即使假设所有索引都在内存中(这更困难,因为索引数量多了 20 倍),mysql 的总数约为 20 次范围查找。

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

因此,对于此示例,与 MongoDB 相比,MySQL 每次逻辑访问的最终统计结果大约是 IO 的20 倍

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

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

相关文章:

c# - Entity Framework 缓慢的第一次调用IRepository DbContext

mongodb - mongo-go-driver 聚合调用总是返回错误

java - 配置 log4j 以使用 mongodb

mysql - 无法在 Laravel 中添加外键

sql - 按照 DTA 的建议添加 NONCLUSTERED INDEX 会提高性能吗?

php - 多个一对一关系 Laravel

java - 为异构键编写 hashCode 方法

ios - 由于 App 传输安全性,Parse-Server 未下载 PFFile

mysql - 子查询返回超过 1 个值。当子查询用作表达式时,这是不允许的。如何修复?

php - 从 mysql 数据库回显随机 ID 号而不重复数字?