性能优化
VEF Framework 应用的性能优化建议。
数据库优化
使用索引
go
type User struct {
orm.Model
Username string `gorm:"size:50;uniqueIndex"`
Email string `gorm:"size:100;index"`
DepartmentId string `gorm:"size:36;index"`
CreatedAt time.Time `gorm:"index"`
}选择必要字段
go
// Good - select only needed fields
apis.NewFindPageApi[models.User, payloads.UserSearch]().
WithSelect("id", "username", "email", "created_at")
// Bad - select all fields
apis.NewFindPageApi[models.User, payloads.UserSearch]()避免 N+1 查询
go
// Good - use preload
apis.NewFindPageApi[models.User, payloads.UserSearch]().
WithPreload("Department", "Roles")
// Bad - query in loop
for _, user := range users {
orm.DB().First(&user.Department, user.DepartmentId)
}批量操作
go
// Good - batch insert
orm.DB().CreateInBatches(users, 100)
// Bad - insert one by one
for _, user := range users {
orm.DB().Create(&user)
}缓存策略
缓存热点数据
go
func (s *ConfigService) Get(key string) (string, error) {
cacheKey := fmt.Sprintf("config:%s", key)
// Try cache first
var value string
if err := cache.Default().Get(cacheKey, &value); err == nil {
return value, nil
}
// Load from database
var config models.Config
if err := orm.DB().First(&config, "key = ?", key).Error; err != nil {
return "", err
}
// Cache for 5 minutes
cache.Default().Set(cacheKey, config.Value, cache.WithTTL(5*time.Minute))
return config.Value, nil
}缓存失效策略
go
// Invalidate on update
func (s *ConfigService) Update(key, value string) error {
if err := orm.DB().Model(&models.Config{}).
Where("key = ?", key).
Update("value", value).Error; err != nil {
return err
}
// Invalidate cache
cache.Default().Delete(fmt.Sprintf("config:%s", key))
return nil
}连接池配置
数据库连接池
yaml
database:
maxIdleConns: 10 # Minimum connections
maxOpenConns: 100 # Maximum connections
connMaxLifetime: 1h # Connection lifetime
connMaxIdleTime: 10m # Idle connection timeoutRedis 连接池
yaml
redis:
poolSize: 10 # Connection pool size
minIdleConns: 5 # Minimum idle connections
maxRetries: 3 # Max retries分页优化
使用游标分页
go
// For large datasets, use cursor-based pagination
type CursorPageParams struct {
Cursor string `json:"cursor"`
PageSize int `json:"pageSize"`
}
func (s *OrderService) FindWithCursor(params CursorPageParams) ([]models.Order, string, error) {
pageSize := params.PageSize
if pageSize <= 0 || pageSize > 100 {
pageSize = 20
}
query := orm.DB().Model(&models.Order{}).Order("created_at DESC, id DESC")
if params.Cursor != "" {
// Decode cursor (timestamp:id)
parts := strings.Split(params.Cursor, ":")
query = query.Where("(created_at, id) < (?, ?)", parts[0], parts[1])
}
var orders []models.Order
query.Limit(pageSize + 1).Find(&orders)
var nextCursor string
if len(orders) > pageSize {
last := orders[pageSize-1]
nextCursor = fmt.Sprintf("%s:%s", last.CreatedAt.Format(time.RFC3339), last.Id)
orders = orders[:pageSize]
}
return orders, nextCursor, nil
}异步处理
使用 goroutine
go
func (r *UserResource) CreateUser(ctx fiber.Ctx, params UserParams) error {
user, err := r.userService.Create(params)
if err != nil {
return api.Error(ctx, err.Error())
}
// Send email asynchronously
go func() {
if err := r.emailService.SendWelcomeEmail(user.Email); err != nil {
log.WithError(err).Error("Failed to send welcome email")
}
}()
return api.Success(ctx, user)
}使用事件总线
go
// Decouple with events
apis.NewCreateApi[models.User, payloads.UserParams]().
WithHook(api.AfterCreate, func(ctx fiber.Ctx, user *models.User) error {
// Publish event instead of direct call
eventbus.PublishAsync(events.UserCreatedEvent{
UserId: user.Id,
Username: user.Username,
Email: user.Email,
})
return nil
})查询优化
使用 Explain 分析
go
// Analyze query performance
var result []map[string]interface{}
orm.DB().Raw("EXPLAIN SELECT * FROM users WHERE department_id = ?", deptId).Scan(&result)
log.WithField("explain", result).Debug("Query explain")避免全表扫描
go
// Good - use index
orm.DB().Where("department_id = ?", deptId).Find(&users)
// Bad - function on column prevents index use
orm.DB().Where("YEAR(created_at) = ?", 2024).Find(&users)
// Better - use range
orm.DB().Where("created_at >= ? AND created_at < ?",
"2024-01-01", "2025-01-01").Find(&users)监控和分析
慢查询日志
yaml
database:
logLevel: "warn" # Log slow queries
slowThreshold: 200ms性能指标
go
// Record API response time
func MetricsMiddleware() fiber.Handler {
return func(ctx *fiber.Ctx) error {
start := time.Now()
err := ctx.Next()
duration := time.Since(start)
// Record metrics
metrics.RecordAPILatency(ctx.Path(), ctx.Method(), duration)
return err
}
}