From 484192072765e0ac8d4347d714dee1fd878b0c3a Mon Sep 17 00:00:00 2001 From: admin Date: Wed, 6 May 2026 08:02:03 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=20cards.go=20?= =?UTF-8?q?=E5=92=8C=20users.go=20=E4=B8=AD=E7=9A=84=20N+1=20=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cards.go: - 合并循环中的 Count 查询为单次 GROUP BY 查询 users.go: - 合并 ownApps 循环查询为单次 IN 查询 - 合并 agentApps 循环查询为批量查询 - 减少数据库查询次数从 O(n) 到 O(1) --- backend/internal/router/admin/cards.go | 26 +++++++++++- backend/internal/router/admin/users.go | 58 +++++++++++++++----------- 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/backend/internal/router/admin/cards.go b/backend/internal/router/admin/cards.go index ad775d4..9be8674 100644 --- a/backend/internal/router/admin/cards.go +++ b/backend/internal/router/admin/cards.go @@ -124,10 +124,32 @@ func handleGetCardTypes(c *gin.Context) { log.Printf("[DEBUG] CardType %d: ID=%d, Name=%s, ApplicationID=%v\n", i, ct.ID, ct.Name, ct.ApplicationID) } + cardTypeIDs := make([]uint, len(cardTypes)) + for i, ct := range cardTypes { + cardTypeIDs[i] = ct.ID + } + + type CardCount struct { + CardTypeID uint + Count int64 + } + var cardCounts []CardCount + if len(cardTypeIDs) > 0 { + database.DB.Model(&model.Card{}). + Select("card_type_id, COUNT(*) as count"). + Where("card_type_id IN ?", cardTypeIDs). + Group("card_type_id"). + Find(&cardCounts) + } + + countMap := make(map[uint]int64) + for _, cc := range cardCounts { + countMap[cc.CardTypeID] = cc.Count + } + var cardTypesWithCount []map[string]interface{} for _, ct := range cardTypes { - var count int64 - database.DB.Model(&model.Card{}).Where("card_type_id = ?", ct.ID).Count(&count) + count := countMap[ct.ID] log.Printf("[DEBUG] CardType ID=%d, Name=%s, GeneratedCount=%d\n", ct.ID, ct.Name, count) cardTypeMap := map[string]interface{}{ diff --git a/backend/internal/router/admin/users.go b/backend/internal/router/admin/users.go index cbea848..cffa1ef 100644 --- a/backend/internal/router/admin/users.go +++ b/backend/internal/router/admin/users.go @@ -125,53 +125,63 @@ func handleGetUsers(c *gin.Context) { appHeartbeatTimeoutMap = make(map[uint]int) - for _, app := range ownApps { + ownAppIDs := make([]uint, len(ownApps)) + for i, app := range ownApps { + ownAppIDs[i] = app.ID timeout := app.HeartbeatTimeout if timeout == 0 { timeout = 300 } appHeartbeatTimeoutMap[app.ID] = timeout + } - var appUsers []model.AppUser - if err := database.DB.Preload("Application").Where("application_id = ?", app.ID).Find(&appUsers).Error; err != nil { + if len(ownAppIDs) > 0 { + if err := database.DB.Preload("Application").Where("application_id IN ?", ownAppIDs).Find(&users).Error; err != nil { response.Error(c, 500, "获取用户列表失败") return } - users = append(users, appUsers...) } - for _, agentApp := range agentApps { - var app model.Application - if err := database.DB.First(&app, agentApp.ApplicationID).Error; err != nil { - log.Printf("[DEBUG] Failed to get application %d: %v", agentApp.ApplicationID, err) - continue - } + agentAppIDs := make([]uint, len(agentApps)) + for i, agentApp := range agentApps { + agentAppIDs[i] = agentApp.ApplicationID + } - log.Printf("[DEBUG] Processing agent app: ApplicationID=%d, AppName=%s", app.ID, app.Name) + var agentAppModels []model.Application + if len(agentAppIDs) > 0 { + database.DB.Where("id IN ?", agentAppIDs).Find(&agentAppModels) + } + agentAppMap := make(map[uint]model.Application) + for _, app := range agentAppModels { + agentAppMap[app.ID] = app timeout := app.HeartbeatTimeout if timeout == 0 { timeout = 300 } appHeartbeatTimeoutMap[app.ID] = timeout + } - var cardUserIDs []uint - if err := database.DB.Model(&model.Card{}). - Where("creator_id = ? AND application_id = ? AND app_user_id IS NOT NULL", userID, app.ID). - Pluck("app_user_id", &cardUserIDs).Error; err != nil { - log.Printf("[DEBUG] Failed to get card user IDs for app %d: %v", app.ID, err) + var allCardUserIDs []uint + for _, agentApp := range agentApps { + app, exists := agentAppMap[agentApp.ApplicationID] + if !exists { continue } + log.Printf("[DEBUG] Processing agent app: ApplicationID=%d, AppName=%s", app.ID, app.Name) - log.Printf("[DEBUG] Found %d card user IDs for app %d: %v", len(cardUserIDs), app.ID, cardUserIDs) + var cardUserIDs []uint + database.DB.Model(&model.Card{}). + Where("creator_id = ? AND application_id = ? AND app_user_id IS NOT NULL", userID, app.ID). + Pluck("app_user_id", &cardUserIDs) + allCardUserIDs = append(allCardUserIDs, cardUserIDs...) + } - if len(cardUserIDs) > 0 { - var appUsers []model.AppUser - if err := database.DB.Preload("Application").Where("id IN ?", cardUserIDs).Find(&appUsers).Error; err != nil { - log.Printf("[DEBUG] Failed to get users for app %d: %v", app.ID, err) - continue - } - log.Printf("[DEBUG] Found %d users for app %d", len(appUsers), app.ID) + if len(allCardUserIDs) > 0 { + var appUsers []model.AppUser + if err := database.DB.Preload("Application").Where("id IN ?", allCardUserIDs).Find(&appUsers).Error; err != nil { + log.Printf("[DEBUG] Failed to get users: %v", err) + } else { users = append(users, appUsers...) } }