Skip to content

Commit

Permalink
修复冗余索引,重复索引检查bug
Browse files Browse the repository at this point in the history
  • Loading branch information
zongfei.fu committed Nov 28, 2023
1 parent 5867bc3 commit 7853d89
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 35 deletions.
2 changes: 1 addition & 1 deletion controllers/inspect/traverse_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ func (c *TraverseCreateTableRedundantIndexes) Enter(in ast.Node) (ast.Node, bool
for _, v := range cons.Keys {
idxColsMap = append(idxColsMap, v.Column.Name.L)
}
c.Redundant.IndexesCols = append(c.Redundant.IndexesCols, process.IndexColsMap{Index: cons.Name, Cols: idxColsMap})
c.Redundant.IndexesCols = append(c.Redundant.IndexesCols, process.IndexColsMap{Index: cons.Name, Cols: idxColsMap, Tag: "is_meta"})
}
}
}
Expand Down
140 changes: 106 additions & 34 deletions controllers/process/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,10 @@ func (i *IndexNumber) CheckPrimaryKeyColsNum() error {
}

// 检查冗余索引
// is_drop:drop操作,is_add:add操作,is_meta:原表表结构
type IndexColsMap struct {
Index string // 索引
Tag string // 标记,值:is_drop/is_add
Tag string // 标记,值:is_drop/is_add/is_meta
Cols []string // 组成索引的列
}
type RedundantIndex struct {
Expand Down Expand Up @@ -161,30 +162,77 @@ func (r *RedundantIndex) CheckRepeatCols() error {
}

func (r *RedundantIndex) CheckRepeatColsWithDiffIndexes() error {
// 查找重复的索引,即索引名不一样,但是定义的列一样,不区分大小写
// 查找重复的索引即索引名不一样但是定义的列一样不区分大小写
// KEY idx_a_b (col1,col2),
// KEY idx_b (col1,col2),
idxCols := make(map[string]bool)
// 获取is_add
var isAddIdxCols []string
// 获取is_drop
var isDropIdxCols []string
// 获取is_meta
isMetaIdxCols := make(map[string]string)
for _, item := range r.IndexesCols {
// 查找重复的索引,即索引名不一样,但是定义的列一样,不区分大小写
// KEY idx_a_b (col1,col2),
// KEY idx_b (col1,col2),
if item.Tag == "is_add" {
isAddIdxCols = append(isAddIdxCols, item.Index)
}
if item.Tag == "is_drop" {
continue
isDropIdxCols = append(isDropIdxCols, item.Index)
}
valueJoin := strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar))
if !idxCols[valueJoin] {
idxCols[valueJoin] = true
} else {
return fmt.Errorf("表`%s`发现了重复定义的索引`%s`,已经存在定义列相同索引`%s`", r.Table, item.Index, strings.Join(item.Cols, ","))
if item.Tag == "is_meta" {
isMetaIdxCols[item.Index] = strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar))
}
}
// 从is_meta数据中删除is_drop的数据
for _, item := range isDropIdxCols {
delete(isMetaIdxCols, item)
}
// 为create table语句
if len(isDropIdxCols) == 0 && len(isAddIdxCols) == 0 {
// 对map中的键进行分组
groups := make(map[string][]string)
for key, value := range isMetaIdxCols {
groups[value] = append(groups[value], key)
}
var result []string
for _, keys := range groups {
if len(keys) > 1 {
result = append(result, strings.Join(keys, "/"))
}
}
if len(result) > 0 {
return fmt.Errorf("表`%s`发现了重复定义的索引:%s", r.Table, strings.Join(result, ";"))
}
} else {
// 为alter table xxx add / drop index
for _, item := range r.IndexesCols {
// 查找重复的索引,即索引名不一样,但是定义的列一样,不区分大小写
// KEY idx_a_b (col1,col2),
// KEY idx_b (col1,col2),
if item.Tag == "is_add" {
found := false
var foundKey string
valueJoin := strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar))
for key, value := range isMetaIdxCols {
if value == valueJoin {
found = true
foundKey = key
break
}
}
if !found {
isMetaIdxCols[item.Index] = valueJoin
} else {
return fmt.Errorf("表`%s`发现了重复定义的索引:%s(%s),请检查原始表结构", r.Table, foundKey, strings.Join(item.Cols, ", "))
}
}
}
}
return nil
}

func (r *RedundantIndex) CheckRedundantColsWithDiffIndexes() error {
/*
查找冗余的索引,即索引名不一样,但是定义的列冗余,不区分大小写
查找冗余的索引即索引名不一样但是定义的列冗余不区分大小写
KEY idx_a (col1),
KEY idx_b (col1,col2),
KEY idx_c (col1,col2,col3)
Expand All @@ -198,42 +246,66 @@ func (r *RedundantIndex) CheckRedundantColsWithDiffIndexes() error {
{IDX_STATUS_UPDATETIME [i_status d_update_time]}
]
*/
var idxCols []string
// idxCols := make(map[string]string)

/*
解决冗余索引时,当指定drop冗余索引时,允许通过
表结构已有索引uniq_aa(`a`, `b`)
添加索引:
ALTER TABLE `tbl1` ADD UNIQUE uniq_bb(`a`,`b`,`c`),DROP INDEX `idx_aa`;
*/
var IsDropIndexes []string
// 找出is_drop的索引操作
// 获取is_drop
var isDropIdxCols []string
// 获取is_meta
isMetaIdxCols := make(map[string]string)
isAddIdxCols := make(map[string]string)

for _, item := range r.IndexesCols {
if item.Tag == "is_add" {
isAddIdxCols[item.Index] = strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar))
}
if item.Tag == "is_drop" {
IsDropIndexes = append(IsDropIndexes, item.Index)
isDropIdxCols = append(isDropIdxCols, item.Index)
}
}
// 从r.IndexesCols中移除is_drop的索引名
for _, item := range r.IndexesCols {
if utils.IsContain(IsDropIndexes, item.Index) {
break
if item.Tag == "is_meta" {
isMetaIdxCols[item.Index] = strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar))
}
idxCols = append(idxCols, strings.ToLower(strings.Join(item.Cols, utils.KeyJoinChar)))
}
// 检查是否存在冗余索引
for _, k := range idxCols {
for _, k1 := range idxCols {
if k == k1 {
continue
// 从is_meta数据中删除is_drop的数据
for _, item := range isDropIdxCols {
delete(isMetaIdxCols, item)
}

// 为create table语句
if len(isDropIdxCols) == 0 && len(isAddIdxCols) == 0 {
var result []string
for k, v := range isMetaIdxCols {
for k1, v1 := range isMetaIdxCols {
if v != v1 {
if strings.HasPrefix(v, v1) && utils.IsSubKey(v, v1) {
result = append(result, strings.Join([]string{k, k1}, "/"))
}
}
}
if strings.HasPrefix(k, k1) && utils.IsSubKey(k, k1) {
return fmt.Errorf("表`%s`发现了冗余索引,冗余索引的字段组合为(%s)/(%s)【您可以增加一个drop原冗余索引的操作】",
r.Table,
strings.Replace(k, utils.KeyJoinChar, ",", -1),
strings.Replace(k1, utils.KeyJoinChar, ",", -1),
)
}
if len(result) > 0 {
return fmt.Errorf("表`%s`发现了冗余索引,冗余索引的字段组合为%s", r.Table, strings.Join(result, ", "))
}
} else {
// 为alter table xxx add / drop index
var result []string
for k, v := range isAddIdxCols {
for k1, v1 := range isMetaIdxCols {
if v != v1 {
if strings.HasPrefix(v, v1) && utils.IsSubKey(v, v1) {
result = append(result, strings.Join([]string{k, k1}, "/"))
}
}
}
}
if len(result) > 0 {
return fmt.Errorf("表`%s`发现了冗余索引,冗余索引的字段组合为%s", r.Table, strings.Join(result, ", "))
}
}
return nil
}
Expand Down

0 comments on commit 7853d89

Please sign in to comment.