init
This commit is contained in:
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user