1. 查询特定日期内完成订单且包含特定产品的订单
- 索引策略:创建复合部分索引,索引字段为
order_date
、order_status
和 products.product_id
。假设完成订单状态为 completed
,仅对 order_status
为 completed
的文档创建索引,示例代码如下(假设使用Node.js的MongoDB驱动):
const { MongoClient } = require('mongodb');
async function createIndex() {
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);
try {
await client.connect();
const database = client.db('ecommerce');
const orders = database.collection('orders');
const indexKeys = {
order_date: 1,
order_status: 1,
'products.product_id': 1
};
const indexOptions = {
partialFilterExpression: {
order_status: 'completed'
}
};
await orders.createIndex(indexKeys, indexOptions);
} finally {
await client.close();
}
}
createIndex().catch(console.error);
- 设计原因:
order_date
作为范围查询字段,放在索引开头可以快速定位到特定日期范围内的文档。
order_status
过滤条件固定为 completed
,通过部分索引仅对符合该条件的文档创建索引,减少索引体积。
products.product_id
用于匹配特定产品,放在最后可以进一步缩小查询范围。
2. 查询某个客户的最近10个订单
- 索引策略:创建复合部分索引,索引字段为
customer_id
和 order_date
,按 order_date
降序排列,仅对 customer_id
不为空的文档创建索引,示例代码如下:
async function createIndex2() {
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);
try {
await client.connect();
const database = client.db('ecommerce');
const orders = database.collection('orders');
const indexKeys = {
customer_id: 1,
order_date: -1
};
const indexOptions = {
partialFilterExpression: {
customer_id: { $ne: null }
}
};
await orders.createIndex(indexKeys, indexOptions);
} finally {
await client.close();
}
}
createIndex2().catch(console.error);
- 设计原因:
customer_id
用于定位特定客户的文档,放在索引开头。
order_date
按降序排列,便于快速获取最近的订单,通过部分索引减少索引体积。
高并发读写场景下可能面临的问题及解决思路
- 问题:
- 索引维护开销:高并发写操作时,索引需要频繁更新,导致性能下降。
- 锁争用:读写操作可能会因为索引的更新而产生锁争用,影响系统并发性能。
- 解决思路:
- 批量操作:将多个写操作合并为批量操作,减少索引更新次数。
- 读写分离:采用读写分离架构,读操作从副本集读取数据,减少主节点的压力。
- 优化索引结构:定期评估索引的使用情况,删除不必要的索引,减少索引维护开销。
- 调整锁粒度:使用细粒度锁,减少锁争用范围,例如在MongoDB中使用文档级锁而非集合级锁。