我对 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/