MST
星途 面试题库

面试题:MongoDB与SQL在多表/集合关联场景下的查询优化

现有一个社交网络数据库,SQL中有users表(包含user_id、name等字段)、posts表(包含post_id、user_id、content等字段)以及comments表(包含comment_id、post_id、user_id、comment_text等字段);MongoDB中有对应的users、posts和comments集合。描述并给出在高并发读取场景下,使用SQL和MongoDB分别如何高效查询某用户发布的所有帖子及其相关评论信息的方案,需考虑查询性能优化及数据一致性等方面。
37.4万 热度难度
数据库MongoDB

知识考点

AI 面试

面试题答案

一键面试

使用SQL方案

  1. 查询思路:通过users表、posts表和comments表之间的连接关系,根据用户ID查询该用户发布的帖子及其评论。
  2. SQL语句
SELECT 
    p.post_id, 
    p.content, 
    c.comment_id, 
    c.comment_text
FROM 
    users u
JOIN 
    posts p ON u.user_id = p.user_id
LEFT JOIN 
    comments c ON p.post_id = c.post_id
WHERE 
    u.user_id = <specific_user_id>;
  1. 性能优化
    • users表的user_id字段、posts表的user_idpost_id字段、comments表的post_iduser_id字段上创建索引,以加快连接和过滤速度。
    • 考虑使用数据库连接池,在高并发场景下减少连接创建和销毁的开销。
  2. 数据一致性
    • 利用事务机制,确保在查询过程中数据的一致性。如果涉及到对这些表的写入操作,需要合理控制事务的边界,避免脏读、不可重复读等问题。

使用MongoDB方案

  1. 查询思路:首先根据用户ID在users集合中找到用户文档,然后使用该用户ID在posts集合中查找其发布的帖子,最后使用帖子ID在comments集合中查找相关评论。
  2. MongoDB查询语句
// 查找用户
const user = db.users.findOne({ user_id: <specific_user_id> });
if (user) {
    // 查找用户发布的帖子
    const posts = db.posts.find({ user_id: <specific_user_id> }).toArray();
    const postIds = posts.map(post => post.post_id);
    // 查找帖子的评论
    const comments = db.comments.find({ post_id: { $in: postIds } }).toArray();
    // 整理结果
    const result = posts.map(post => {
        const postComments = comments.filter(comment => comment.post_id === post.post_id);
        return {
            post_id: post.post_id,
            content: post.content,
            comments: postComments
        };
    });
    return result;
}
  1. 性能优化
    • users集合的user_id字段、posts集合的user_idpost_id字段、comments集合的post_iduser_id字段上创建索引,以加快查询速度。
    • 使用聚合管道优化查询,减少多次查询带来的性能损耗。例如:
db.posts.aggregate([
    { $match: { user_id: <specific_user_id> } },
    {
        $lookup: {
            from: "comments",
            localField: "post_id",
            foreignField: "post_id",
            as: "comments"
        }
    }
]);
  1. 数据一致性
    • MongoDB 4.0及以上版本支持多文档事务,可以在需要保证数据一致性的场景下使用事务。对于查询操作,由于不涉及写入,通常不会有数据一致性问题,但如果在查询期间数据有写入操作,可能会读到部分新数据部分旧数据,可通过设置适当的读偏好(read preference)来解决,如设置为primaryPreferred,优先从主节点读取数据,以获取最新数据。