84 lines
3.3 KiB
Go
84 lines
3.3 KiB
Go
package business
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type businessQueryIndex struct {
|
|
table, name string
|
|
columns []string
|
|
}
|
|
|
|
var businessQueryIndexes = []businessQueryIndex{
|
|
{"tab_promote", "idx_sw_promote_created", []string{"source_db", "create_time", "id"}},
|
|
{"tab_spend", "idx_sw_spend_time_summary", []string{"pay_status", "pay_time", "source_db", "pay_amount"}},
|
|
{"tab_spend", "idx_sw_spend_promote_summary", []string{"promote_id", "pay_status", "source_db", "pay_amount"}},
|
|
{"tab_sw_report_day", "idx_sw_report_pay_scan", []string{"dedup_mode", "stat_date", "source_db", "promote_id", "game_id", "total_pay"}},
|
|
{"tab_sw_report_day_key", "idx_sw_report_key_scan", []string{"dedup_mode", "stat_date", "source_db", "promote_id", "game_id", "metric", "identity_key"}},
|
|
{"tab_sw_report_server_day", "idx_sw_server_pay_game_scan", []string{"game_name", "dedup_mode", "stat_date", "source_db", "game_id", "server_num", "total_pay"}},
|
|
{"tab_sw_report_server_day_key", "idx_sw_server_key_game_scan", []string{"game_name", "dedup_mode", "stat_date", "source_db", "game_id", "server_num", "metric", "identity_key"}},
|
|
}
|
|
|
|
var reportBuildQueryIndexes = []businessQueryIndex{
|
|
{"tab_user", "idx_sw_user_report_identity", []string{"id", "source_db", "puid", "promote_id", "idcard"}},
|
|
{"tab_user_play_info", "idx_sw_play_report_active", []string{"play_time", "user_id", "source_db", "promote_id", "game_id", "server_id"}},
|
|
}
|
|
|
|
// 只为已经接入的业务表增加索引,不创建平台表、不改写记录。
|
|
// 按实际筛选前缀排列,并覆盖聚合读取列,避免大范围回表。
|
|
func migrateBusinessQueryIndexes(db *gorm.DB) error {
|
|
return migrateQueryIndexes(db, businessQueryIndexes)
|
|
}
|
|
|
|
func migrateReportBuildQueryIndexes(db *gorm.DB) error {
|
|
return migrateQueryIndexes(db, reportBuildQueryIndexes)
|
|
}
|
|
|
|
func migrateQueryIndexes(db *gorm.DB, indexes []businessQueryIndex) error {
|
|
if db.Dialector.Name() != "mysql" {
|
|
return nil
|
|
}
|
|
groups := make(map[string][]businessQueryIndex)
|
|
tables := []string{}
|
|
for _, index := range indexes {
|
|
if _, exists := groups[index.table]; !exists {
|
|
tables = append(tables, index.table)
|
|
}
|
|
groups[index.table] = append(groups[index.table], index)
|
|
}
|
|
for _, table := range tables {
|
|
available, err := businessTableAvailable(db, table)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !available {
|
|
continue
|
|
}
|
|
additions := []string{}
|
|
for _, index := range groups[table] {
|
|
var existing []string
|
|
if err := db.Raw("SELECT column_name FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name=? AND index_name=? ORDER BY seq_in_index", index.table, index.name).Scan(&existing).Error; err != nil {
|
|
return err
|
|
}
|
|
if len(existing) > 0 {
|
|
if strings.Join(existing, ",") != strings.Join(index.columns, ",") {
|
|
return fmt.Errorf("%s.%s 的现有索引列不符", index.table, index.name)
|
|
}
|
|
continue
|
|
}
|
|
columns := "`" + strings.Join(index.columns, "`,`") + "`"
|
|
additions = append(additions, "ADD INDEX `"+index.name+"` ("+columns+")")
|
|
}
|
|
// 同一大表的多个索引合并构建,减少重复扫描。
|
|
if len(additions) > 0 {
|
|
if err := db.Exec("ALTER TABLE `" + table + "` " + strings.Join(additions, ",") + ", ALGORITHM=INPLACE, LOCK=NONE").Error; err != nil {
|
|
return fmt.Errorf("add query indexes on %s: %w", table, err)
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|