@@ -21,6 +21,7 @@ type idxAdvPool []*IdxAdvisor
21
21
const queryChanSize int = 10000
22
22
23
23
var registeredIdxAdv = make (map [uint64 ]* IdxAdvisor )
24
+
24
25
var idxadvPool idxAdvPool = make (idxAdvPool , 0 )
25
26
26
27
func (iap * idxAdvPool ) push (ia * IdxAdvisor ) {
@@ -65,8 +66,6 @@ func (ci CandidateIdxes) Less(i, j int) bool { return ci[i].Benefit > ci[j].Bene
65
66
func (ci CandidateIdxes ) Swap (i , j int ) { ci [i ], ci [j ] = ci [j ], ci [i ] }
66
67
67
68
// NewIdxAdv create a new IdxAdvisor.
68
- // TODO: *sql.DB is not supposed to a member of IdxAdvisor.
69
- // *sql.DB can interacts with idxadvisor by session variable
70
69
func NewIdxAdv (db * sql.DB ) * IdxAdvisor {
71
70
ia := & IdxAdvisor {dbClient : db }
72
71
ia .ready .Store (false )
@@ -75,14 +74,15 @@ func NewIdxAdv(db *sql.DB) *IdxAdvisor {
75
74
return ia
76
75
}
77
76
78
- // MockNewIdxAdv() return *IdxAdvisor without initiating dbClient member
77
+ // MockNewIdxAdv return *IdxAdvisor without initiating dbClient member
79
78
func MockNewIdxAdv () * IdxAdvisor {
80
79
ia := & IdxAdvisor {}
81
80
ia .ready .Store (false )
82
81
idxadvPool .push (ia )
83
82
return ia
84
83
}
85
84
85
+ // GetIdxAdv returns a IdxAdvisor according to connID.
86
86
func GetIdxAdv (connID uint64 ) * IdxAdvisor {
87
87
if ia , ok := registeredIdxAdv [connID ]; ok {
88
88
return ia
@@ -96,45 +96,6 @@ func GetIdxAdv(connID uint64) *IdxAdvisor {
96
96
}
97
97
}
98
98
99
- //// GetRecommendIdx return recommend index within given connection
100
- //func GetRecommendIdx(connID uint64) (*CandidateIdxes, error) {
101
- // if ia, ok := registeredIdxAdv[connID]; !ok {
102
- // return nil, errors.New(fmt.Sprintf(
103
- // "bad attempt to get recommend index with no registered index advisor. connID: %v\n", connID))
104
- // } else {
105
- // return &ia.Candidate_idx, nil
106
- // }
107
- //}
108
-
109
- // GetRecommendIdxStr return recommend index in string format. Used in test
110
- func GetRecommendIdxStr (connID uint64 ) (string , error ) {
111
- if ia , ok := registeredIdxAdv [connID ]; ! ok {
112
- return "" , errors .New (fmt .Sprintf (
113
- "bad attempt to get recommend index with no registered index advisor. connID: %v\n " , connID ))
114
- } else {
115
- idxes := ia .Candidate_idx
116
- if len (idxes ) == 0 {
117
- return "" , nil
118
- }
119
-
120
- var idxesStr string
121
- for _ , idx := range idxes {
122
- var idxStr string
123
- idxStr = fmt .Sprintf ("%s: (" , idx .Index .Index .Table .L )
124
- cols := idx .Index .Index .Columns
125
- colLen := len (cols )
126
-
127
- for i := 0 ; i < len (cols )- 1 ; i ++ {
128
- idxStr = fmt .Sprintf ("%s%s " , idxStr , cols [i ].Name .L )
129
- }
130
-
131
- idxStr = fmt .Sprintf ("%s%s)" , idxStr , cols [colLen - 1 ].Name .L )
132
- idxesStr = fmt .Sprintf ("%s%s," , idxesStr , idxStr )
133
- }
134
- return idxesStr [:len (idxesStr )- 1 ], nil
135
- }
136
- }
137
-
138
99
// Init set session variable tidb_enable_index_advisor = true
139
100
func (ia * IdxAdvisor ) Init () error {
140
101
ia .queryChan = make (chan string , queryChanSize )
@@ -168,7 +129,7 @@ func (ia *IdxAdvisor) StartTask(sqlFile string) {
168
129
query , ok := <- ia .queryChan
169
130
if ! ok {
170
131
// No more query
171
- WriteFinaleResult ()
132
+ WriteFinalResult ()
172
133
return
173
134
}
174
135
fmt .Printf ("**************************************[%v]******************************************\n " , cnt )
@@ -177,93 +138,6 @@ func (ia *IdxAdvisor) StartTask(sqlFile string) {
177
138
}
178
139
}
179
140
180
- //func readQuery(sqlFile *string, queryChan chan string) {
181
- // fd, _ := os.Open(*sqlFile)
182
- // defer func() {
183
- // fd.Close()
184
- // close(queryChan)
185
- // }()
186
- //
187
- // scanner := bufio.NewScanner(fd)
188
- //
189
- // // TODO: more efficient way to extract select statement from file
190
- // maxCap := bufio.MaxScanTokenSize
191
- // buf := make([]byte, maxCap)
192
- // scanner.Buffer(buf, maxCap)
193
- // split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
194
- // // Define a split function that separates on "--"
195
- // for i := 0; i < len(data)-1; i++ {
196
- // if data[i] == 0x2d && data[i+1] == 0x2d {
197
- // return i + 2, data[:i], nil
198
- //
199
- // }
200
- //
201
- // }
202
- // return 0, data, bufio.ErrFinalToken
203
- // }
204
- // scanner.Split(split)
205
- //
206
- // // Scan
207
- // cnt := 1
208
- // for scanner.Scan() {
209
- // contents := scanner.Text()
210
- // // fmt.Printf("================================[%v]==================================\n", cnt)
211
- // // fmt.Printf("%v\n", contents)
212
- // sqlBegin := strings.Index(string(contents), "select")
213
- // query := contents[sqlBegin : len(contents)-1]
214
- // queryChan <- query
215
- // cnt++
216
- // }
217
- //
218
- // if err := scanner.Err(); err != nil {
219
- // fmt.Fprintln(os.Stderr, "reading input:", err)
220
- // }
221
- //}
222
-
223
- func readQuery (sqlFile string , queryChan chan string ) {
224
- defer func () {
225
- close (queryChan )
226
- }()
227
-
228
- // If readQuery is called in idxadv_test.go, return immediately
229
- if sqlFile == "test-mode" {
230
- return
231
- }
232
-
233
- files , err := ioutil .ReadDir (sqlFile )
234
- if err != nil {
235
- panic (err )
236
- }
237
-
238
- n := len (files )
239
-
240
- for i := 1 ; i <= n ; i ++ {
241
- sqlfile := sqlFile + strconv .Itoa (i ) + ".sql"
242
-
243
- contents , err := ioutil .ReadFile (sqlfile )
244
- if err != nil {
245
- panic (err )
246
- }
247
- // sqlBegin := strings.Index(string(contents), "select")
248
- // query := contents[sqlBegin:]
249
- queryChan <- string (contents )
250
- }
251
- }
252
-
253
- /*
254
- // StartTask start handling queries in idxadv mode after session variable tidb_enable_index_advisor has been set
255
- func (ia *IdxAdvisor) StartTask(query string) {
256
- if ia.IsReady() {
257
- // var err error
258
- sqlFile := "/tmp/queries"
259
- queries := readQuery(&sqlFile)
260
- for i, query := range queries {
261
- fmt.Printf("$$$$$$$$$$$$$$$$$$$$$$[%v]$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n", i+1)
262
- ia.dbClient.Exec(query)
263
- }
264
- }
265
- }
266
- */
267
141
func GetVirtualInfoschema (is infoschema.InfoSchema , dbName string , tableInfoSets map [string ]* plannercore.TableInfoSets ) infoschema.InfoSchema {
268
142
// Get a copy of InfoSchema
269
143
dbInfos := is .Clone ()
@@ -280,7 +154,7 @@ func GetVirtualInfoschema(is infoschema.InfoSchema, dbName string, tableInfoSets
280
154
idxInfo := tblCopy .Meta ().Indices
281
155
282
156
// add virtual indexes to InfoSchemaCopy.TblInfo
283
- virtualIndexes := BuildVirtualIndexes (tblInfoCopy , dbname , tblname , tblInfoSets )
157
+ virtualIndexes := buildVirtualIndexes (tblInfoCopy , dbname , tblname , tblInfoSets )
284
158
for _ , virtualIndex := range virtualIndexes {
285
159
if ! isExistedInTable (virtualIndex , idxInfo ) {
286
160
tblInfoCopy .Indices = append (tblInfoCopy .Indices , virtualIndex )
@@ -290,14 +164,14 @@ func GetVirtualInfoschema(is infoschema.InfoSchema, dbName string, tableInfoSets
290
164
return ISCopy
291
165
}
292
166
293
- func BuildVirtualIndexes (tblInfo * model.TableInfo , dbname , tblname model.CIStr , tblInfoSets * plannercore.TableInfoSets ) []* model.IndexInfo {
294
- indexes := GenVirtualIndexCols (tblInfo , dbname , tblname , tblInfoSets )
167
+ func buildVirtualIndexes (tblInfo * model.TableInfo , dbname , tblname model.CIStr , tblInfoSets * plannercore.TableInfoSets ) []* model.IndexInfo {
168
+ indexes := genVirtualIndexCols (tblInfo , dbname , tblname , tblInfoSets )
295
169
result := make ([]* model.IndexInfo , 0 )
296
170
for i , idxColNames := range indexes {
297
171
indexName := model .NewCIStr ("vIndex" + string (i ))
298
172
indexinfo , err := ddl .BuildIndexInfo (tblInfo , indexName , idxColNames , model .StatePublic )
299
173
if err != nil {
300
- fmt .Printf ("BuildVirtualIndexes error: %v!\n " , err )
174
+ fmt .Printf ("buildVirtualIndexes error: %v!\n " , err )
301
175
var idxColNameStr string
302
176
for _ , idxCol := range idxColNames {
303
177
idxColNameStr = fmt .Sprintf ("%v %v" , idxColNameStr , idxCol )
@@ -310,14 +184,14 @@ func BuildVirtualIndexes(tblInfo *model.TableInfo, dbname, tblname model.CIStr,
310
184
return result
311
185
}
312
186
313
- func GenVirtualIndexCols (tblInfo * model.TableInfo , dbname , tblname model.CIStr , tblInfoSets * plannercore.TableInfoSets ) [][]* ast.IndexColName {
187
+ func genVirtualIndexCols (tblInfo * model.TableInfo , dbname , tblname model.CIStr , tblInfoSets * plannercore.TableInfoSets ) [][]* ast.IndexColName {
314
188
columnInfos := tblInfo .Columns
315
189
var result [][]* ast.IndexColName
316
190
317
191
// one column
318
192
for _ , columnInfo := range columnInfos {
319
193
idxCols := make ([]* ast.IndexColName , 1 , 1 )
320
- idxCols [0 ] = BuildIdxColNameFromColInfo (columnInfo , dbname , tblname )
194
+ idxCols [0 ] = buildIdxColNameFromColInfo (columnInfo , dbname , tblname )
321
195
result = append (result , idxCols )
322
196
}
323
197
@@ -327,8 +201,8 @@ func GenVirtualIndexCols(tblInfo *model.TableInfo, dbname, tblname model.CIStr,
327
201
for j := 0 ; j < nCols ; j ++ {
328
202
if i != j {
329
203
idxTwoCols := make ([]* ast.IndexColName , 2 , 2 )
330
- idxTwoCols [0 ] = BuildIdxColNameFromColInfo (columnInfos [i ], dbname , tblname )
331
- idxTwoCols [1 ] = BuildIdxColNameFromColInfo (columnInfos [j ], dbname , tblname )
204
+ idxTwoCols [0 ] = buildIdxColNameFromColInfo (columnInfos [i ], dbname , tblname )
205
+ idxTwoCols [1 ] = buildIdxColNameFromColInfo (columnInfos [j ], dbname , tblname )
332
206
result = append (result , idxTwoCols )
333
207
}
334
208
}
@@ -391,12 +265,11 @@ func GenVirtualIndexCols(tblInfo *model.TableInfo, dbname, tblname model.CIStr,
391
265
}
392
266
}
393
267
if isExisted {
394
- idxCols = append (idxCols , BuildIdxColNameFromColInfo (columnInfo , dbname , tblname ))
268
+ idxCols = append (idxCols , buildIdxColNameFromColInfo (columnInfo , dbname , tblname ))
395
269
}
396
270
}
397
271
result = append (result , idxCols )
398
272
}
399
-
400
273
return result
401
274
}
402
275
@@ -412,26 +285,18 @@ func addToCandidateCols(readyCols []model.CIStr, cols *[]model.CIStr, candidateC
412
285
}
413
286
}
414
287
415
- func BuildIdxColNameFromColInfo (colInfo * model.ColumnInfo , dbname , tblname model.CIStr ) * ast.IndexColName {
288
+ func buildIdxColNameFromColInfo (colInfo * model.ColumnInfo , dbname , tblname model.CIStr ) * ast.IndexColName {
416
289
idxColName := & ast.IndexColName {}
417
290
idxColName .Column = & ast.ColumnName {Schema : dbname , Table : tblname , Name : colInfo .Name }
418
291
idxColName .Length = - 1
419
292
return idxColName
420
293
}
421
294
422
- func GenIndexCols (index * model.IndexInfo ) []model.CIStr {
423
- cols := []model.CIStr {}
424
- for _ , idxColumn := range index .Columns {
425
- cols = append (cols , idxColumn .Name )
426
- }
427
- return cols
428
- }
429
-
430
295
func isExistedInTable (virtualIndex * model.IndexInfo , indices []* model.IndexInfo ) bool {
431
296
is := false
432
- virtualIndexCols := GenIndexCols (virtualIndex )
297
+ virtualIndexCols := genIndexCols (virtualIndex )
433
298
for _ , idx := range indices {
434
- indexCols := GenIndexCols (idx )
299
+ indexCols := genIndexCols (idx )
435
300
if reflect .DeepEqual (virtualIndexCols , indexCols ) {
436
301
is = true
437
302
break
@@ -440,6 +305,14 @@ func isExistedInTable(virtualIndex *model.IndexInfo, indices []*model.IndexInfo)
440
305
return is
441
306
}
442
307
308
+ func genIndexCols (index * model.IndexInfo ) []model.CIStr {
309
+ cols := []model.CIStr {}
310
+ for _ , idxColumn := range index .Columns {
311
+ cols = append (cols , idxColumn .Name )
312
+ }
313
+ return cols
314
+ }
315
+
443
316
func (ia * IdxAdvisor ) addCandidate (virtualIdx * CandidateIdx ) {
444
317
in := false
445
318
for _ , candidateIdx := range ia .Candidate_idx {
@@ -454,3 +327,31 @@ func (ia *IdxAdvisor) addCandidate(virtualIdx *CandidateIdx) {
454
327
ia .Candidate_idx = append (ia .Candidate_idx , virtualIdx )
455
328
}
456
329
}
330
+
331
+ func readQuery (sqlFile string , queryChan chan string ) {
332
+ defer func () {
333
+ close (queryChan )
334
+ }()
335
+
336
+ // If readQuery is called in idxadv_test.go, return immediately
337
+ if sqlFile == "test-mode" {
338
+ return
339
+ }
340
+
341
+ files , err := ioutil .ReadDir (sqlFile )
342
+ if err != nil {
343
+ panic (err )
344
+ }
345
+
346
+ n := len (files )
347
+
348
+ for i := 1 ; i <= n ; i ++ {
349
+ sqlfile := sqlFile + strconv .Itoa (i ) + ".sql"
350
+
351
+ contents , err := ioutil .ReadFile (sqlfile )
352
+ if err != nil {
353
+ panic (err )
354
+ }
355
+ queryChan <- string (contents )
356
+ }
357
+ }
0 commit comments