diff --git a/MONGODB_INDEXES.md b/MONGODB_INDEXES.md new file mode 100644 index 0000000..35e8acb --- /dev/null +++ b/MONGODB_INDEXES.md @@ -0,0 +1,141 @@ +# MongoDB 索引创建指南 + +本项目使用 MongoDB 作为数据库,为了确保良好的查询性能,需要手动创建以下索引。 + +## 连接到 MongoDB + +```bash +# 连接到 MongoDB +mongo mongodb://localhost:27017/jimeng-api + +# 或者使用 MongoDB Compass 等图形工具 +``` + +## 需要创建的索引 + +### 1. 生成任务表 (jimeng_free_generation_tasks) + +```javascript +// 基础索引 +db.jimeng_free_generation_tasks.createIndex({ "task_id": 1 }, { unique: true }); +db.jimeng_free_generation_tasks.createIndex({ "server_id": 1 }); +db.jimeng_free_generation_tasks.createIndex({ "status": 1 }); +db.jimeng_free_generation_tasks.createIndex({ "created_at": 1 }); +db.jimeng_free_generation_tasks.createIndex({ "next_poll_at": 1 }); + +// 复合索引 - 用于轮询查询优化 +db.jimeng_free_generation_tasks.createIndex({ + "server_id": 1, + "status": 1, + "next_poll_at": 1 +}); + +// 复合索引 - 用于服务器负载查询 +db.jimeng_free_generation_tasks.createIndex({ + "server_id": 1, + "created_at": 1 +}); +``` + +### 2. 生成结果表 (jimeng_free_generation_results) + +```javascript +// 基础索引 +db.jimeng_free_generation_results.createIndex({ "task_id": 1 }, { unique: true }); +db.jimeng_free_generation_results.createIndex({ "server_id": 1 }); +db.jimeng_free_generation_results.createIndex({ "created_at": 1 }); + +// TTL索引 - 自动清理过期记录 +db.jimeng_free_generation_results.createIndex({ + "expires_at": 1 +}, { + expireAfterSeconds: 0 +}); + +// 复合索引 +db.jimeng_free_generation_results.createIndex({ + "server_id": 1, + "created_at": 1 +}); +``` + +### 3. 服务器心跳表 (jimeng_servers) + +```javascript +// 基础索引 +db.jimeng_servers.createIndex({ "server_id": 1 }, { unique: true }); +db.jimeng_servers.createIndex({ "last_heartbeat": 1 }); + +// 复合索引 - 用于查询在线服务器 +db.jimeng_servers.createIndex({ + "is_active": 1, + "last_heartbeat": 1 +}); +``` + +## 一键执行脚本 + +将以下内容保存为 `create_indexes.js` 文件,然后执行: + +```javascript +// create_indexes.js +print("开始创建 jimeng-free-api 数据库索引..."); + +// 生成任务表索引 +db = db.getSiblingDB('jimeng-api'); + +print("创建生成任务表索引..."); +db.jimeng_free_generation_tasks.createIndex({ "task_id": 1 }, { unique: true }); +db.jimeng_free_generation_tasks.createIndex({ "server_id": 1 }); +db.jimeng_free_generation_tasks.createIndex({ "status": 1 }); +db.jimeng_free_generation_tasks.createIndex({ "created_at": 1 }); +db.jimeng_free_generation_tasks.createIndex({ "next_poll_at": 1 }); +db.jimeng_free_generation_tasks.createIndex({ "server_id": 1, "status": 1, "next_poll_at": 1 }); +db.jimeng_free_generation_tasks.createIndex({ "server_id": 1, "created_at": 1 }); + +print("创建生成结果表索引..."); +db.jimeng_free_generation_results.createIndex({ "task_id": 1 }, { unique: true }); +db.jimeng_free_generation_results.createIndex({ "server_id": 1 }); +db.jimeng_free_generation_results.createIndex({ "created_at": 1 }); +db.jimeng_free_generation_results.createIndex({ "expires_at": 1 }, { expireAfterSeconds: 0 }); +db.jimeng_free_generation_results.createIndex({ "server_id": 1, "created_at": 1 }); + +print("创建服务器心跳表索引..."); +db.jimeng_servers.createIndex({ "server_id": 1 }, { unique: true }); +db.jimeng_servers.createIndex({ "last_heartbeat": 1 }); +db.jimeng_servers.createIndex({ "is_active": 1, "last_heartbeat": 1 }); + +print("所有索引创建完成!"); +``` + +执行命令: +```bash +mongo mongodb://localhost:27017/jimeng-api create_indexes.js +``` + +## 验证索引 + +创建完成后,可以验证索引是否正确创建: + +```javascript +// 查看所有集合的索引 +db.jimeng_free_generation_tasks.getIndexes(); +db.jimeng_free_generation_results.getIndexes(); +db.jimeng_servers.getIndexes(); +``` + +## 性能说明 + +- **唯一索引**:确保 task_id 和 server_id 的唯一性 +- **复合索引**:优化多字段查询,特别是轮询任务时的复杂查询 +- **TTL 索引**:自动清理过期的结果记录,释放存储空间 +- **时间索引**:加速基于时间的查询和排序 + +这些索引的创建顺序不影响功能,但建议按照文档顺序执行以确保最佳性能。 + +## 注意事项 + +1. **数据库名称**:请根据实际使用的数据库名称调整脚本中的 `jimeng-api` +2. **连接地址**:请根据实际的 MongoDB 连接地址调整命令 +3. **权限要求**:执行索引创建需要数据库的写权限 +4. **生产环境**:在生产环境中创建索引可能需要考虑对性能的影响,建议在低峰期执行 \ No newline at end of file diff --git a/src/lib/database/models/GenerationResult.ts b/src/lib/database/models/GenerationResult.ts index 92684a0..be8e3e8 100644 --- a/src/lib/database/models/GenerationResult.ts +++ b/src/lib/database/models/GenerationResult.ts @@ -30,8 +30,7 @@ const GenerationResultSchema: Schema = new Schema({ task_id: { type: String, required: true, - unique: true, - index: true + unique: true }, task_type: { type: String, @@ -40,8 +39,7 @@ const GenerationResultSchema: Schema = new Schema({ }, server_id: { type: String, - required: true, - index: true + required: true }, status: { type: String, @@ -66,25 +64,15 @@ const GenerationResultSchema: Schema = new Schema({ }, created_at: { type: Number, - default: () => Math.floor(Date.now() / 1000), - index: true + default: () => Math.floor(Date.now() / 1000) }, expires_at: { type: Number, - required: true, - index: true + required: true } }, { collection: 'jimeng_free_generation_results', timestamps: false // 使用自定义时间戳 }); -// 创建索引 -GenerationResultSchema.index({ task_id: 1 }); -GenerationResultSchema.index({ expires_at: 1 }); // 用于过期清理 -GenerationResultSchema.index({ server_id: 1, created_at: 1 }); - -// 设置TTL索引,自动清理过期记录 -GenerationResultSchema.index({ expires_at: 1 }, { expireAfterSeconds: 0 }); - export default mongoose.model('GenerationResult', GenerationResultSchema); \ No newline at end of file diff --git a/src/lib/database/models/GenerationTask.ts b/src/lib/database/models/GenerationTask.ts index a51f013..55a2302 100644 --- a/src/lib/database/models/GenerationTask.ts +++ b/src/lib/database/models/GenerationTask.ts @@ -59,8 +59,7 @@ const GenerationTaskSchema: Schema = new Schema({ task_id: { type: String, required: true, - unique: true, - index: true + unique: true }, task_type: { type: String, @@ -69,8 +68,7 @@ const GenerationTaskSchema: Schema = new Schema({ }, server_id: { type: String, - required: true, - index: true + required: true }, original_params: { model: String, @@ -100,8 +98,7 @@ const GenerationTaskSchema: Schema = new Schema({ type: String, required: true, enum: ['pending', 'processing', 'polling', 'completed', 'failed'], - default: 'pending', - index: true + default: 'pending' }, retry_count: { type: Number, @@ -112,8 +109,7 @@ const GenerationTaskSchema: Schema = new Schema({ default: 3 }, next_poll_at: { - type: Number, - index: true + type: Number }, poll_interval: { type: Number, @@ -125,8 +121,7 @@ const GenerationTaskSchema: Schema = new Schema({ }, created_at: { type: Number, - default: () => Math.floor(Date.now() / 1000), - index: true + default: () => Math.floor(Date.now() / 1000) }, updated_at: { type: Number, @@ -141,12 +136,4 @@ const GenerationTaskSchema: Schema = new Schema({ timestamps: false // 使用自定义时间戳 }); -// 创建复合索引 - 用于轮询查询 -GenerationTaskSchema.index({ server_id: 1, status: 1, next_poll_at: 1 }); - -// 创建其他索引 -GenerationTaskSchema.index({ task_id: 1 }); -GenerationTaskSchema.index({ created_at: 1 }); -GenerationTaskSchema.index({ updated_at: 1 }); - export default mongoose.model('GenerationTask', GenerationTaskSchema); \ No newline at end of file diff --git a/src/lib/database/models/ServiceHeartbeat.ts b/src/lib/database/models/ServiceHeartbeat.ts index 157aa9a..d53e0b8 100644 --- a/src/lib/database/models/ServiceHeartbeat.ts +++ b/src/lib/database/models/ServiceHeartbeat.ts @@ -16,8 +16,7 @@ const JimengServerSchema: Schema = new Schema({ server_id: { type: String, required: true, - unique: true, - index: true + unique: true }, server_name: { type: String, @@ -33,8 +32,7 @@ const JimengServerSchema: Schema = new Schema({ }, last_heartbeat: { type: Number, - default: 0, - index: true + default: 0 }, heartbeat_interval: { type: Number, @@ -53,8 +51,4 @@ const JimengServerSchema: Schema = new Schema({ timestamps: false // 使用自定义时间戳 }); -// 创建索引 -JimengServerSchema.index({ server_id: 1 }); -JimengServerSchema.index({ is_active: 1, last_heartbeat: 1 }); - export default mongoose.model('JimengServer', JimengServerSchema); \ No newline at end of file diff --git a/src/lib/services/HeartbeatService.ts b/src/lib/services/HeartbeatService.ts index 0cacdcc..5e16220 100644 --- a/src/lib/services/HeartbeatService.ts +++ b/src/lib/services/HeartbeatService.ts @@ -55,7 +55,6 @@ export class HeartbeatService { private getLocalIP(): string | null { try { - const os = require('os'); const interfaces = os.networkInterfaces(); // 优先查找非回环的IPv4地址