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
+121
View File
@@ -0,0 +1,121 @@
package commands
import (
"fmt"
"strings"
"github.com/goravel/framework/contracts/console"
"github.com/goravel/framework/contracts/console/command"
"github.com/goravel/framework/facades"
)
type OptimizeTables struct {
}
func (r *OptimizeTables) Signature() string {
return "db:optimize-tables"
}
func (r *OptimizeTables) Description() string {
// # MySQL: OPTIMIZE TABLE(整理碎片,回收空间)
// # PostgreSQL: VACUUM (ANALYZE)(清理死元组并更新统计信息)
//
// # 传参方式:直接传表名(可多个)
// go run . artisan db:optimize-tables payments
// go run . artisan db:optimize-tables payments orders_202601 order_details_202601
//
// # 选项方式:--tables= 逗号分隔
// go run . artisan db:optimize-tables --tables=payments,orders_202601
//
// # PostgreSQL 重度回收空间(风险高:会锁表,且耗时长)
// go run . artisan db:optimize-tables payments --full=true
//
// # 帮助
// go run . artisan db:optimize-tables --help
return "优化表(MySQL: OPTIMIZE TABLE; PostgreSQL: VACUUM"
}
func (r *OptimizeTables) Extend() command.Extend {
return command.Extend{
Category: "db",
Flags: []command.Flag{
&command.StringFlag{
Name: "tables",
Aliases: []string{"t"},
Usage: "要优化的表名列表(逗号分隔),也可以直接用参数方式传入多个表名",
},
&command.BoolFlag{
Name: "full",
Value: false,
Usage: "PostgreSQL 是否使用 VACUUM FULL(更重,可能锁表,默认 false",
},
},
}
}
func (r *OptimizeTables) Handle(ctx console.Context) error {
dbConnection := strings.ToLower(facades.Config().GetString("database.default", "sqlite"))
full := ctx.OptionBool("full")
var tables []string
// 1) 从 --tables 读取(逗号分隔)
tablesFlag := strings.TrimSpace(ctx.Option("tables"))
if tablesFlag != "" {
parts := strings.Split(tablesFlag, ",")
for _, p := range parts {
t := strings.TrimSpace(p)
if t != "" {
tables = append(tables, t)
}
}
}
// 2) 从参数读取(db:optimize-tables table1 table2 ...
for i := 0; ; i++ {
arg := strings.TrimSpace(ctx.Argument(i))
if arg == "" {
break
}
tables = append(tables, arg)
}
if len(tables) == 0 {
return fmt.Errorf("请提供要优化的表名,例如:go run . artisan db:optimize-tables payments 或使用 --tables=payments,orders_202601")
}
execOptimize := func(table string) error {
var sql string
switch dbConnection {
case "mysql":
sql = fmt.Sprintf("OPTIMIZE TABLE `%s`", table)
case "postgres":
if full {
sql = fmt.Sprintf("VACUUM (FULL, ANALYZE) %s", table)
} else {
sql = fmt.Sprintf("VACUUM (ANALYZE) %s", table)
}
default:
return fmt.Errorf("unsupported database: %s", dbConnection)
}
if _, err := facades.Orm().Query().Exec(sql); err != nil {
return err
}
ctx.Info("✓ " + sql)
return nil
}
ctx.Info("开始执行优化...")
for _, table := range tables {
if facades.Schema().HasTable(table) {
if err := execOptimize(table); err != nil {
return fmt.Errorf("optimize %s failed: %v", table, err)
}
}
}
ctx.Info("完成")
return nil
}