This commit is contained in:
Joe
2026-01-16 15:49:34 +08:00
commit 550d3e1f42
380 changed files with 62024 additions and 0 deletions
+162
View File
@@ -0,0 +1,162 @@
package commands
import (
"fmt"
"strings"
"time"
"github.com/goravel/framework/contracts/console"
"github.com/goravel/framework/contracts/console/command"
"github.com/goravel/framework/facades"
"goravel/app/utils"
)
type AnalyzeStats struct {
}
func (r *AnalyzeStats) Signature() string {
return "db:analyze-stats"
}
func (r *AnalyzeStats) Description() string {
// # 默认:分析当前月+上个月的 orders/order_details 分表,并分析 payments 表
// go run . artisan db:analyze-stats
//
// # 指定向前分析几个月(含当前月)
// go run . artisan db:analyze-stats --months=2
// go run . artisan db:analyze-stats --months=6
//
// # 指定某一个月(只分析该月的分表)
// go run . artisan db:analyze-stats --month=202601
//
// # 只分析订单分表,不分析支付表
// go run . artisan db:analyze-stats --payments=false
//
// # 只分析 payments 表
// go run . artisan db:analyze-stats --orders=false --order-details=false
//
// # 帮助
// go run . artisan db:analyze-stats --help
return "更新订单分表与支付表统计信息(ANALYZE)"
}
func (r *AnalyzeStats) Extend() command.Extend {
return command.Extend{
Category: "db",
Flags: []command.Flag{
&command.StringFlag{
Name: "month",
Aliases: []string{"m"},
Usage: "指定月份(格式: YYYYMM,如:202512),不指定则按 months 向前分析",
},
&command.IntFlag{
Name: "months",
Aliases: []string{"n"},
Value: 2,
Usage: "向前分析几个月(默认2:当前月+上个月)",
},
&command.BoolFlag{
Name: "orders",
Value: true,
Usage: "是否分析订单分表(orders_YYYYMM",
},
&command.BoolFlag{
Name: "order-details",
Value: true,
Usage: "是否分析订单详情分表(order_details_YYYYMM",
},
&command.BoolFlag{
Name: "payments",
Value: true,
Usage: "是否分析支付记录表(payments",
},
},
}
}
func (r *AnalyzeStats) Handle(ctx console.Context) error {
dbConnection := strings.ToLower(facades.Config().GetString("database.default", "sqlite"))
monthsFlag := ctx.OptionInt("months")
if monthsFlag <= 0 {
monthsFlag = 2
}
monthFlag := strings.TrimSpace(ctx.Option("month"))
analyzeOrders := ctx.OptionBool("orders")
analyzeOrderDetails := ctx.OptionBool("order-details")
analyzePayments := ctx.OptionBool("payments")
var months []time.Time
if monthFlag != "" {
parsedTime, err := time.ParseInLocation("200601", monthFlag, time.UTC)
if err != nil {
return fmt.Errorf("月份格式错误,应为 YYYYMM 格式(如:202512): %v", err)
}
months = []time.Time{parsedTime}
} else {
now := time.Now().UTC()
currentMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.UTC)
for i := 0; i < monthsFlag; i++ {
months = append(months, currentMonth.AddDate(0, -i, 0))
}
}
ctx.Info("开始执行 ANALYZE...")
execAnalyze := func(table string) error {
var sql string
switch dbConnection {
case "mysql":
sql = fmt.Sprintf("ANALYZE TABLE `%s`", table)
case "postgres":
sql = fmt.Sprintf("ANALYZE %s", table)
default:
return fmt.Errorf("unsupported database: %s", dbConnection)
}
_, err := facades.Orm().Query().Exec(sql)
if err != nil {
return err
}
ctx.Info("✓ " + sql)
return nil
}
if analyzeOrders {
for _, m := range months {
table := utils.GetShardingTableName("orders", m)
if facades.Schema().HasTable(table) {
if err := execAnalyze(table); err != nil {
return fmt.Errorf("analyze %s failed: %v", table, err)
}
}
}
}
if analyzeOrderDetails {
for _, m := range months {
table := utils.GetShardingTableName("order_details", m)
if facades.Schema().HasTable(table) {
if err := execAnalyze(table); err != nil {
return fmt.Errorf("analyze %s failed: %v", table, err)
}
}
}
}
if analyzePayments {
if facades.Schema().HasTable("payments") {
if err := execAnalyze("payments"); err != nil {
return fmt.Errorf("analyze payments failed: %v", err)
}
}
}
ctx.Info("完成")
return nil
}