perf: 修复 cards.go 和 users.go 中的 N+1 查询问题
cards.go: - 合并循环中的 Count 查询为单次 GROUP BY 查询 users.go: - 合并 ownApps 循环查询为单次 IN 查询 - 合并 agentApps 循环查询为批量查询 - 减少数据库查询次数从 O(n) 到 O(1)
This commit is contained in:
@@ -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)
|
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{}
|
var cardTypesWithCount []map[string]interface{}
|
||||||
for _, ct := range cardTypes {
|
for _, ct := range cardTypes {
|
||||||
var count int64
|
count := countMap[ct.ID]
|
||||||
database.DB.Model(&model.Card{}).Where("card_type_id = ?", ct.ID).Count(&count)
|
|
||||||
log.Printf("[DEBUG] CardType ID=%d, Name=%s, GeneratedCount=%d\n", ct.ID, ct.Name, count)
|
log.Printf("[DEBUG] CardType ID=%d, Name=%s, GeneratedCount=%d\n", ct.ID, ct.Name, count)
|
||||||
|
|
||||||
cardTypeMap := map[string]interface{}{
|
cardTypeMap := map[string]interface{}{
|
||||||
|
|||||||
@@ -125,53 +125,63 @@ func handleGetUsers(c *gin.Context) {
|
|||||||
|
|
||||||
appHeartbeatTimeoutMap = make(map[uint]int)
|
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
|
timeout := app.HeartbeatTimeout
|
||||||
if timeout == 0 {
|
if timeout == 0 {
|
||||||
timeout = 300
|
timeout = 300
|
||||||
}
|
}
|
||||||
appHeartbeatTimeoutMap[app.ID] = timeout
|
appHeartbeatTimeoutMap[app.ID] = timeout
|
||||||
|
}
|
||||||
|
|
||||||
var appUsers []model.AppUser
|
if len(ownAppIDs) > 0 {
|
||||||
if err := database.DB.Preload("Application").Where("application_id = ?", app.ID).Find(&appUsers).Error; err != nil {
|
if err := database.DB.Preload("Application").Where("application_id IN ?", ownAppIDs).Find(&users).Error; err != nil {
|
||||||
response.Error(c, 500, "获取用户列表失败")
|
response.Error(c, 500, "获取用户列表失败")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
users = append(users, appUsers...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, agentApp := range agentApps {
|
agentAppIDs := make([]uint, len(agentApps))
|
||||||
var app model.Application
|
for i, agentApp := range agentApps {
|
||||||
if err := database.DB.First(&app, agentApp.ApplicationID).Error; err != nil {
|
agentAppIDs[i] = agentApp.ApplicationID
|
||||||
log.Printf("[DEBUG] Failed to get application %d: %v", agentApp.ApplicationID, err)
|
}
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
timeout := app.HeartbeatTimeout
|
||||||
if timeout == 0 {
|
if timeout == 0 {
|
||||||
timeout = 300
|
timeout = 300
|
||||||
}
|
}
|
||||||
appHeartbeatTimeoutMap[app.ID] = timeout
|
appHeartbeatTimeoutMap[app.ID] = timeout
|
||||||
|
}
|
||||||
|
|
||||||
var cardUserIDs []uint
|
var allCardUserIDs []uint
|
||||||
if err := database.DB.Model(&model.Card{}).
|
for _, agentApp := range agentApps {
|
||||||
Where("creator_id = ? AND application_id = ? AND app_user_id IS NOT NULL", userID, app.ID).
|
app, exists := agentAppMap[agentApp.ApplicationID]
|
||||||
Pluck("app_user_id", &cardUserIDs).Error; err != nil {
|
if !exists {
|
||||||
log.Printf("[DEBUG] Failed to get card user IDs for app %d: %v", app.ID, err)
|
|
||||||
continue
|
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 {
|
if len(allCardUserIDs) > 0 {
|
||||||
var appUsers []model.AppUser
|
var appUsers []model.AppUser
|
||||||
if err := database.DB.Preload("Application").Where("id IN ?", cardUserIDs).Find(&appUsers).Error; err != nil {
|
if err := database.DB.Preload("Application").Where("id IN ?", allCardUserIDs).Find(&appUsers).Error; err != nil {
|
||||||
log.Printf("[DEBUG] Failed to get users for app %d: %v", app.ID, err)
|
log.Printf("[DEBUG] Failed to get users: %v", err)
|
||||||
continue
|
} else {
|
||||||
}
|
|
||||||
log.Printf("[DEBUG] Found %d users for app %d", len(appUsers), app.ID)
|
|
||||||
users = append(users, appUsers...)
|
users = append(users, appUsers...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user