当前位置: 首页 > 面试题库 >

MySQL vs MongoDB 1000读取

齐浩淼
2023-03-14
问题内容

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

我想将速度与MongoDB进行比较,然后运行了一个测试,该测试将从我们的大型数据库中随机获取并打印15条记录。我为mysql和MongoDB分别运行了约1,000次查询,但我很惊讶我没有注意到速度上的很大差异。也许MongoDB快1.1倍。真令人失望。我做错什么了吗?我知道我的测试并不完美,但是在阅读繁琐的杂物方面,MySQL与MongoDb相当。

注意:

  • 我有双核+(2个线程)i7 cpu和4GB ram
  • 我在MySQL上有20个分区,每个分区有1百万条记录

用于测试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相比,每个逻辑访问的最终IO数比MySQL多 20倍

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



 类似资料:
  • 我在尝试生成一个简单DF的共线性分析时遇到了问题(见下文)。我的问题是,每次尝试运行该函数时,都会检索到以下错误消息: 下面是我正在使用的代码 我试图运行函数的DF如下所示。 我在这里有两个猜测;但不知道如何解决这个问题: -猜测1:np。arrange导致与标头发生某种冲突 -猜想2:问题来自blankseperator,它阻止函数正确地从一列跳转到另一列。问题是,我的CSV文件已经有分隔符(我

  • 问题内容: 我有一个Flask,SQLAlchemy webapp,它使用一个mysql服务器。我想将数据库设置扩展为具有只读从​​属服务器,以便可以在继续写入主数据库服务器的同时在主服务器和从属服务器之间分散读取。 我研究了几种选择,我相信我无法使用普通的SQLAlchemy做到这一点。我打算在我的web应用程序中创建2个数据库句柄,每个用于主数据库服务器和从数据库服务器。然后,使用简单的随机值

  • 问题内容: 在Golang中处理原始IP软件包时,遇到了一个问题,我似乎无法找到以下解决方案: 在IPv4的说明书中包含有大于8位小字段。例如,版本或报头长度(每个4位)或标志(3位)。 如何从io.Reader中读取这些值,然后再使用Golang处理它们?到目前为止,我一直在使用binary.Read方法,但是由于Golang中最小的整数类型是int8,因此在这种情况下是不可能的。 问题答案:

  •  未读部分指玩家还没有执行过的剧本、已读部分则是玩家已经看过的部分。  KAG 中,支持未读/已读部分的文字显示速度不同,已读部分的 [l] 指令无效等功能。  未读/已读,是使用系统变量进行记录的、命名格式以 trail_ 开头。要进行未读/已读记录,请在 Config.tjs 里将 autoRecordPageShowing 设为 true 。 未读部分和已读部分  KAG 中、未读部分/已读

  • 问题内容: 我是Java的新手,所以如果这是一个很小的错误,请原谅我,这是 我的代码: 当我在编译后运行它时,第18行(n = System.in.read())被跳过。 我得到的输出是这样的: 对(1-5)投票: 1输入0退出,再次输入1投票: 对(1-5)投票: 2输入0退出,再次输入1投票: 对(1)投票-5): ^ C 的值not 会使程序成为无限循环。 谢谢您的帮助。 问题答案: 我认为

  • 我是一名铁锈新手,尝试阅读两个数字并计算它们的商: 但是当我试图编译它时,我得到了以下错误重复了几次: src/safe_div.rs:12: 12:12:21错误:不匹配类型:预期

  • 我试图读取3温度设备使用WinForm和Modbus 485协议。基本上,我必须定期向每个设备写入命令,等待响应,当我得到响应时,处理它。每个设备都有一个唯一的通信地址。为了定期发送命令,我使用了计时器。这就是我发送命令的方式和处理响应的地方: 对于每个设备,等等。这是我的serialport数据接收事件: 所以我的沟通应该是: 然后再次发送命令device1。问题是,我有时得到通信超时错误,我知

  • TensorFlow程序读取数据一共有3种方法: 供给数据(Feeding): 在TensorFlow程序运行的每一步, 让Python代码来供给数据。 从文件读取数据: 在TensorFlow图的起始, 让一个输入管线从文件中读取数据。 预加载数据: 在TensorFlow图中定义常量或变量来保存所有数据(仅适用于数据量比较小的情况)。 目录 数据读取 供给数据(Feeding) 从文件读取数据