这个 Mongo 查询和这个 SQL 查询一样吗?我是不是正确地考虑了Mongo?
Posted
技术标签:
【中文标题】这个 Mongo 查询和这个 SQL 查询一样吗?我是不是正确地考虑了Mongo?【英文标题】:Is this Mongo query the same as this SQL query? Am I thinking about Mongo correctly?这个 Mongo 查询和这个 SQL 查询一样吗?我是否正确地考虑了Mongo? 【发布时间】:2014-05-07 12:06:35 【问题描述】:这并不是负面的,因为我一直在阅读 Mongo 文档。我对这个概念很陌生。 Mongo 被吹捧为这个正在扼杀 mysql 的超高效数据库,但我读到的所有 Mongo 语句似乎都可以简化为,因此没有更高效的 SQL。也许我采取了错误的方法。
假设您有两个表:
User
ID Name FavoriteColor
1 John 1
2 Jona 2
3 Jack 1
Color
ID Name
1 Red
2 Green
3 Blue
为了获得用户的颜色,我会这样做
SELECT
`u`.`Name`,
`c`.`color`
FROM `user` AS `u`
LEFT JOIN `color` AS `c` ON `u`.`FavoriteColor` = `c`.`id`
不确定该语法是否正确,我面前没有 MySQL。
现在 Mongo 不支持连接(人们说这是 Mongo 的重点)所以如果我要这样做,我会迭代用户集合,然后对于每条记录,我会根据该用户最喜欢的颜色 ID 查询颜色数据库和“迭代”颜色集合(应该只返回一行)。但这似乎与(在 php 中)完全相同:
<?
$query = "SELECT `Name`, `FavoriteColor` FROM `users`";
$result = mysql_query($query);
while($row = mysql_fetch_array($result))
$username = $row["Name"];
$query = "SELECT `Name` FROM `Color` WHERE `id` = " . $row["FavoriteColor"] . " LIMIT 1";
$result = mysql_query($query);
$color = "";
//I know we return only one row but I am illustrating the concept of scanning the entire color table
while($row2 = mysql_fetch_array($result))
$color = $row2["Name"];
echo "Hi I'm $username and my favorite color is $color <br>";
?>
从效率的角度来看,我看不出 MongoDB 如何比 SQL 更快(join 或 php 迭代方式似乎仍然是同一件事)。归根结底,它必须扫描整个用户表,并且对于每个用户,它必须扫描整个颜色表以将 colorID 与最喜欢的颜色匹配。
我应该尝试从逻辑上减少 MongoDB 存储到行\列\表中,还是 MongoDB 本身的执行方式不同?
【问题讨论】:
这是一个非常好的问题,来自我的 +1。现在我只需要等待 Mongo ***者在不自掘坟墓的情况下尝试解释这一点 :) 【参考方案1】:您对 MongoDb 中缺乏加入支持是正确的。它允许 MongoDB 集合自动分布,而不会被要求在两个分布式集合(表)之间加入。如果可能的话,这将导致在服务器上进行大量工作,并且根本无法扩展。
所以它不支持连接,但它是面向文档的数据库,它支持嵌入文档。它极大地影响了数据库结构设计。现在您可以选择是嵌入还是创建新的集合(表),具体选择取决于数据本身和数据使用模式,因此您需要提前了解您的数据使用模式。
回到您的示例,这两个表可能会合并到一个集合中user
,您可能会有这样的事情:
name: John,
favoriteColor: Red
在这种情况下,检索相同数据不需要连接。是完全不同的结构设计。但是,MongoDB 不支持约束(唯一性除外),您需要注意不要尝试使用不存在的颜色。为此,您可以有单独的 color
集合,并在将数据插入集合 user
时检查数据。
总结: MongoDB 的效率不在于更快地执行相同的操作,而在于能够使用不同的范式对旧问题进行建模。
【讨论】:
我也可以在 SQL 用户表中添加“红色”,但有时人们有两个表,因为假设红色、绿色和蓝色是唯一可用的颜色。我为他们准备了一个单独的表格,这样我就可以查询该表格来填充下拉列表或其他内容。在 MongoLand 中,您会按照您的描述进行操作,然后单独收集可用颜色吗? 如果您需要约束值,您仍然可以在 MongoDB 中单独收集颜色。这里没有黑魔法。您也可以将 Red 放入 SQL 用户表中(尽管它会破坏规范化)。但是让我们超越那个简单的例子,想象用户可以有多种不同的颜色,也可以有一些偏好,也可以有一些设置。在 MongoDb 中,您可以将所有这些内容放在一个文档中,并提供丰富的查询选项,此外,是否可以通过副本集具有持久性并通过分片进行分发。【参考方案2】:为了能够理解 MongoDb,您需要尝试抛开您在 RDBMS 中所学的知识。
MongoDB 是一个“动态模式”系统,是一个基于文档的数据库,围绕对象概念的数据。
在您发布的示例中,您使用的结构仍在为您的设计实现更多的关系数据库方法。为了扩展复杂数据和开发速度,并记住没有加入支持,我建议您重新审视您的设计并“去规范化”您的集合,即使您认为它可能看起来多余(基于如何数据库已经设计了 40 年)
【讨论】:
【参考方案3】:首先,Mongo 可能正在杀死 MYSQL,但它甚至还没有接近 MYSQL。
User
ID Name FavoriteColor
1 John RED
2 Jona GREEN
3 Jack RED
这就是您的数据在 mongo 中的外观。 Mongo 不支持连接,但支持嵌入式文档。如果您要经常查询该数据,则始终建议您将数据放入 mongo 中的单个集合中。简而言之,将没有颜色表/集合。最有可能的是,获取用户和颜色的查询是
db.collection.find(,name:1,favoriteColor:1)
您的收藏文档将如下所示。
id: 1
name: John
FavCol: RED
【讨论】:
你知道这根本没有回答问题吗? 我不会尝试向您解释这个问题,但您基本上重复了OP在他的帖子中提到的内容。把这个作为答案是愚蠢的。 @N.B.我也不需要你的解释,你最好读 10 到 15 遍,也许你会有所了解:) 无论如何谢谢。 看来这里的语言障碍太大了,我就让你和隐形敌人和紫色独角兽展开你的网络战争。以上是关于这个 Mongo 查询和这个 SQL 查询一样吗?我是不是正确地考虑了Mongo?的主要内容,如果未能解决你的问题,请参考以下文章
将Mongo查询转换为spring Mongooperations