当前位置:首页 > 未命名 > 正文内容

MongoDB数据库设计与性能优化

廖万里9小时前未命名0

MongoDB概述

MongoDB是面向文档的NoSQL数据库,以JSON格式存储数据,支持灵活的Schema设计和强大的查询能力。

MongoDB vs 关系型数据库

概念MongoDBMySQL
数据库DatabaseDatabase
表/集合CollectionTable
行/文档DocumentRow
列/字段FieldColumn
主键_idPrimary Key
索引IndexIndex

文档设计

嵌入式文档 vs 引用

// 嵌入式文档(一对一、一对少)
{
  "_id": ObjectId("..."),
  "name": "John Doe",
  "email": "john@example.com",
  "address": {
    "street": "123 Main St",
    "city": "New York",
    "zip": "10001"
  }
}

// 引用方式(一对多、多对多)
// users collection
{
  "_id": ObjectId("user1"),
  "name": "John Doe"
}

// orders collection
{
  "_id": ObjectId("order1"),
  "userId": ObjectId("user1"),
  "products": [
    { "productId": ObjectId("prod1"), "quantity": 2 }
  ]
}

// 使用populate(Mongoose)
const user = await User.findById(userId).populate('orders');

Schema设计原则

  1. 频繁一起访问的数据嵌入
  2. 频繁更新的数据单独存储
  3. 超过16MB限制的数组使用引用
  4. 考虑读写比例设计

CRUD操作

// 插入文档
db.users.insertOne({
  name: "Alice",
  email: "alice@example.com",
  age: 25,
  tags: ["developer", "nodejs"]
});

db.users.insertMany([
  { name: "Bob", email: "bob@example.com" },
  { name: "Charlie", email: "charlie@example.com" }
]);

// 查询
db.users.findOne({ name: "Alice" });

db.users.find({ 
  age: { $gte: 20, $lte: 30 },
  tags: "nodejs"
});

// 投影
db.users.find({}, { name: 1, email: 1, _id: 0 });

// 排序、分页
db.users.find()
  .sort({ age: -1 })
  .skip(10)
  .limit(10);

// 更新
db.users.updateOne(
  { name: "Alice" },
  { $set: { age: 26 }, $push: { tags: "python" } }
);

db.users.updateMany(
  { age: { $lt: 18 } },
  { $set: { status: "minor" } }
);

// 删除
db.users.deleteOne({ name: "Bob" });
db.users.deleteMany({ status: "inactive" });

聚合管道

// 基本聚合
db.orders.aggregate([
  // 筛选
  { $match: { status: "completed" } },
  
  // 展开
  { $unwind: "$products" },
  
  // 分组统计
  {
    $group: {
      _id: "$products.category",
      totalSales: { $sum: "$products.price" },
      count: { $sum: 1 },
      avgPrice: { $avg: "$products.price" }
    }
  },
  
  // 排序
  { $sort: { totalSales: -1 } },
  
  // 限制结果
  { $limit: 10 },
  
  // 重命名字段
  {
    $project: {
      category: "$_id",
      totalSales: 1,
      count: 1,
      _id: 0
    }
  }
]);

// Lookup关联查询
db.orders.aggregate([
  {
    $lookup: {
      from: "users",
      localField: "userId",
      foreignField: "_id",
      as: "userDetails"
    }
  },
  { $unwind: "$userDetails" }
]);

索引优化

// 创建索引
db.users.createIndex({ email: 1 }, { unique: true });

// 复合索引
db.orders.createIndex({ userId: 1, createdAt: -1 });

// 文本索引
db.articles.createIndex({ title: "text", content: "text" });
db.articles.find({ $text: { $search: "mongodb tutorial" } });

// 地理空间索引
db.places.createIndex({ location: "2dsphere" });
db.places.find({
  location: {
    $near: {
      $geometry: { type: "Point", coordinates: [-73.97, 40.77] },
      $maxDistance: 1000
    }
  }
});

// 查看索引
db.users.getIndexes();

// 分析查询性能
db.users.find({ email: "test@example.com" }).explain("executionStats");

// 索引策略
// ESR原则:Equality(等值) → Sort(排序) → Range(范围)
db.orders.createIndex({ status: 1, createdAt: -1, amount: 1 });
// 查询:status = "pending", sort by createdAt, filter by amount > 100

Python驱动

from pymongo import MongoClient, ASCENDING, DESCENDING
from bson import ObjectId
from datetime import datetime

# 连接
client = MongoClient('mongodb://localhost:27017/')
db = client['mydb']

# 插入
result = db.users.insert_one({
    'name': 'Alice',
    'email': 'alice@example.com',
    'created_at': datetime.now()
})
print(f"Inserted ID: {result.inserted_id}")

# 批量插入
users = [{'name': f'User {i}'} for i in range(100)]
result = db.users.insert_many(users)

# 查询
user = db.users.find_one({'_id': ObjectId('...')})
for user in db.users.find({'age': {'$gte': 20}}).sort('name'):
    print(user)

# 更新
result = db.users.update_one(
    {'name': 'Alice'},
    {'$set': {'age': 26}, '$currentDate': {'updated_at': True}}
)

# 聚合
pipeline = [
    {'$match': {'status': 'active'}},
    {'$group': {'_id': '$department', 'count': {'$sum': 1}}},
    {'$sort': {'count': -1}}
]
for doc in db.users.aggregate(pipeline):
    print(doc)

# 事务(副本集)
with client.start_session() as session:
    with session.start_transaction():
        db.accounts.update_one(
            {'_id': ObjectId('...')},
            {'$inc': {'balance': -100}},
            session=session
        )
        db.accounts.update_one(
            {'_id': ObjectId('...')},
            {'$inc': {'balance': 100}},
            session=session
        )

性能优化

监控命令

// 服务器状态
db.serverStatus()

// 数据库统计
db.stats()

// 集合统计
db.users.stats()

// 慢查询日志
db.setProfilingLevel(1, 50)  // 记录超过50ms的查询
db.system.profile.find().sort({ts: -1}).limit(10)

优化建议

  1. 合理设计Schema:根据访问模式嵌入或引用
  2. 创建合适索引:覆盖查询,避免全表扫描
  3. 限制返回字段:使用投影减少网络传输
  4. 批量操作:使用insertMany/updateMany
  5. 读写分离:副本集读取从节点

MongoDB是现代应用的强大数据存储选择,合理的设计和优化能够支撑大规模应用。

MongoDB Collection Document MongoDB文档数据库

本文链接:https://www.kkkliao.cn/?id=755 转载需授权!

分享到:

版权声明:本文由廖万里的博客发布,如需转载请注明出处。


发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。