跳到主要内容

MongoDB 大数据量优化

1. 大数据量场景下的性能问题诊断

面试题1:面对千万级数据的 MongoDB 集合,查询性能急剧下降,你会如何系统性地排查问题?

解答要点:

大数据量性能问题排查需要遵循系统性的方法论,从监控指标到具体优化都要有章法。

性能问题排查流程:

系统性排查步骤:

// 1. 开启详细的性能监控
db.setProfilingLevel(1, { slowms: 50 })

// 2. 查看数据库整体状态
db.stats()
db.serverStatus()

// 3. 分析集合统计信息
db.collection.stats()

// 4. 检查索引效率
db.collection.aggregate([
{ $indexStats: {} }
])

// 5. 分析工作集大小
db.serverStatus().wiredTiger.cache

面试题2:在大数据量环境下,MongoDB 的工作集(Working Set)管理对性能有什么影响?

解答要点:

工作集是指 MongoDB 经常访问的数据和索引部分,理想情况下应该完全缓存在内存中。

工作集管理时序图:

工作集优化策略:

// 监控缓存命中率
db.serverStatus().wiredTiger.cache

// 关键指标:
// - bytes currently in the cache: 当前缓存使用量
// - maximum bytes configured: 最大缓存配置
// - pages read into cache: 从磁盘读取的页数
// - pages written from cache: 写回磁盘的页数

2. 索引设计与优化策略

面试题3:在亿级数据场景下,如何设计和维护高效的索引策略?

解答要点:

大数据量场景下的索引设计需要平衡查询性能、存储空间和写入性能。

大数据量索引设计流程:

索引优化实战代码:

// 1. 分析查询选择性
db.collection.aggregate([
{
$group: {
_id: "$fieldName",
count: { $sum: 1 }
}
},
{
$group: {
_id: null,
uniqueValues: { $sum: 1 },
totalDocs: { $sum: "$count" }
}
},
{
$project: {
selectivity: { $divide: ["$uniqueValues", "$totalDocs"] }
}
}
])

// 2. 创建部分索引(减少索引大小)
db.collection.createIndex(
{ status: 1, createdAt: -1 },
{
partialFilterExpression: {
status: { $in: ["active", "pending"] }
}
}
)

// 3. 创建稀疏索引
db.collection.createIndex(
{ optionalField: 1 },
{ sparse: true }
)

// 4. TTL索引用于数据过期
db.collection.createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 2592000 } // 30天后过期
)

面试题4:如何处理索引维护对大数据量写入性能的影响?

解答要点:

大数据量写入时,索引维护是主要的性能瓶颈之一。

索引维护性能影响分析:

写入性能优化策略:

// 1. 后台构建索引,减少锁定时间
db.collection.createIndex(
{ field: 1 },
{ background: true }
)

// 2. 使用无序插入提高性能
db.collection.insertMany(
documents,
{ ordered: false }
)

// 3. 合理的批次大小
const batchSize = 1000;
for (let i = 0; i < totalDocs; i += batchSize) {
const batch = documents.slice(i, i + batchSize);
db.collection.insertMany(batch, { ordered: false });
}

// 4. 写关注点优化
db.collection.insertMany(
documents,
{
writeConcern: { w: 1, j: false },
ordered: false
}
)

3. 分片架构设计与优化

面试题5:设计一个支持百亿级数据的 MongoDB 分片架构,需要考虑哪些关键因素?

解答要点:

百亿级数据的分片架构设计需要从片键选择、分片策略、硬件配置等多个维度考虑。

分片架构设计流程:

分片架构关键配置:

// 1. 启用分片
sh.enableSharding("database_name")

// 2. 创建复合片键
sh.shardCollection(
"database_name.collection_name",
{
"userId": "hashed",
"timestamp": 1
}
)

// 3. 预分片策略
for (let i = 0; i < 1024; i++) {
sh.splitAt(
"database_name.collection_name",
{ "userId": ObjectId(), "timestamp": new Date() }
)
}

// 4. 平衡器配置
sh.setBalancerState(true)
sh.startBalancer()

// 配置平衡窗口
use config
db.settings.update(
{ _id: "balancer" },
{
$set: {
activeWindow: {
start: "01:00",
stop: "05:00"
}
}
},
{ upsert: true }
)

面试题6:如何解决分片环境下的查询性能问题和数据倾斜问题?

解答要点:

分片环境下的性能问题主要来源于查询路由策略和数据分布不均。

分片查询优化时序图:

数据倾斜解决方案:

数据倾斜监控和修复:

// 1. 检查分片数据分布
sh.status()

// 2. 查看各分片的数据统计
db.adminCommand("listShards").shards.forEach(function(shard){
print("Shard: " + shard._id)
print("Host: " + shard.host)
})

// 3. 手动分片
sh.splitAt(
"database.collection",
{ "shardKey": "splitValue" }
)

// 4. 移动分片块
sh.moveChunk(
"database.collection",
{ "shardKey": "value" },
"target-shard"
)

// 5. 监控分片均衡状态
sh.isBalancerRunning()
sh.getBalancerState()

// 6. 修改片键(MongoDB 4.2+)
db.adminCommand({
refineCollectionShardKey: "database.collection",
key: {
existingKey: 1,
newField: 1
}
})

4. 内存和存储优化

面试题7:大数据量场景下,如何优化 MongoDB 的内存使用和存储引擎配置?

解答要点:

大数据量环境下,内存和存储的优化直接影响整体性能表现。

内存使用优化策略:

存储引擎配置优化:

// 1. WiredTiger 缓存配置
// mongod.conf
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 32 // 通常设置为总内存的 50-60%
directoryForIndexes: true
collectionConfig:
blockCompressor: snappy // 或 zlib, zstd
indexConfig:
prefixCompression: true

// 2. 监控内存使用
db.serverStatus().wiredTiger.cache
db.serverStatus().mem

// 3. 查看集合压缩情况
db.collection.stats().wiredTiger.compression

// 4. 手动触发压缩
db.runCommand({compact: "collection_name"})

面试题8:在存储空间有限的情况下,如何实现大数据量的归档和清理策略?

解答要点:

大数据量的生命周期管理需要自动化的归档和清理机制。

数据生命周期管理流程:

自动化清理策略实现:

// 1. TTL 索引自动清理
db.logs.createIndex(
{ "createdAt": 1 },
{ expireAfterSeconds: 7776000 } // 90天自动删除
)

// 2. 基于时间的数据归档脚本
function archiveOldData() {
const cutoffDate = new Date();
cutoffDate.setMonth(cutoffDate.getMonth() - 6); // 6个月前的数据

const pipeline = [
{ $match: { createdAt: { $lt: cutoffDate } } },
{ $out: "archived_collection" }
];

// 归档数据
db.main_collection.aggregate(pipeline);

// 删除已归档的数据
const result = db.main_collection.deleteMany({
createdAt: { $lt: cutoffDate }
});

print(`Archived and deleted ${result.deletedCount} documents`);
}

// 3. 分批删除大量数据(避免锁定)
function batchDelete(collection, query, batchSize = 1000) {
let deletedCount = 0;

while (true) {
const result = db[collection].deleteMany(
query,
{ limit: batchSize }
);

deletedCount += result.deletedCount;

if (result.deletedCount < batchSize) {
break;
}

// 短暂停顿,避免长时间占用资源
sleep(100);
}

return deletedCount;
}

// 4. 数据压缩和空间回收
db.runCommand({compact: "collection_name", force: true})

5. 监控和性能调优

面试题9:构建一套完整的 MongoDB 大数据量监控体系需要关注哪些核心指标?

解答要点:

完整的监控体系需要覆盖性能、容量、可用性等多个维度。

监控体系架构:

关键监控指标配置:

// 1. 性能监控指标
const performanceMetrics = {
// 查询性能
avgQueryTime: "db.serverStatus().opcounters",
slowQueries: "db.system.profile.find().count()",

// 内存使用
cacheHitRatio: "db.serverStatus().wiredTiger.cache",
memoryUsage: "db.serverStatus().mem",

// 连接状态
currentConnections: "db.serverStatus().connections.current",
availableConnections: "db.serverStatus().connections.available",

// 锁状态
lockWaitTime: "db.serverStatus().globalLock.currentQueue",

// 复制状态(副本集)
replicationLag: "rs.status()",
oplogWindow: "db.getReplicationInfo()"
}

// 2. 自动化监控脚本
function collectMetrics() {
const metrics = {
timestamp: new Date(),
serverStatus: db.serverStatus(),
dbStats: db.stats(),
replStatus: rs.status()
};

// 发送到监控系统
return metrics;
}

// 3. 告警阈值配置
const alertThresholds = {
slowQueryTime: 1000, // 慢查询阈值 1秒
connectionUsage: 0.8, // 连接使用率 80%
cacheHitRate: 0.9, // 缓存命中率 90%
replicationLag: 10, // 复制延迟 10秒
diskUsage: 0.85 // 磁盘使用率 85%
}