Skip to content

Commit bcfcfba

Browse files
zimulalawinkyao
authored andcommitted
*: speed up the operation of "admin check table" (pingcap#8572, pingcap#1156… (pingcap#11676)
1 parent 339fd43 commit bcfcfba

File tree

14 files changed

+729
-208
lines changed

14 files changed

+729
-208
lines changed

ddl/db_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4616,6 +4616,22 @@ func (s *testDBSuite) TestAddIndexForGeneratedColumn(c *C) {
46164616
s.mustExec(c, "delete from t where y = 2155")
46174617
s.mustExec(c, "alter table t add index idx_y(y1)")
46184618
s.mustExec(c, "alter table t drop index idx_y")
4619+
4620+
// Fix issue 9311.
4621+
s.tk.MustExec("create table gcai_table (id int primary key);")
4622+
s.tk.MustExec("insert into gcai_table values(1);")
4623+
s.tk.MustExec("ALTER TABLE gcai_table ADD COLUMN d date DEFAULT '9999-12-31';")
4624+
s.tk.MustExec("ALTER TABLE gcai_table ADD COLUMN d1 date as (DATE_SUB(d, INTERVAL 31 DAY));")
4625+
s.tk.MustExec("ALTER TABLE gcai_table ADD INDEX idx(d1);")
4626+
s.tk.MustQuery("select * from gcai_table").Check(testkit.Rows("1 9999-12-31 9999-11-30"))
4627+
s.tk.MustQuery("select d1 from gcai_table use index(idx)").Check(testkit.Rows("9999-11-30"))
4628+
s.tk.MustExec("admin check table gcai_table")
4629+
// The column is PKIsHandle in generated column expression.
4630+
s.tk.MustExec("ALTER TABLE gcai_table ADD COLUMN id1 int as (id+5);")
4631+
s.tk.MustExec("ALTER TABLE gcai_table ADD INDEX idx1(id1);")
4632+
s.tk.MustQuery("select * from gcai_table").Check(testkit.Rows("1 9999-12-31 9999-11-30 6"))
4633+
s.tk.MustQuery("select id1 from gcai_table use index(idx1)").Check(testkit.Rows("6"))
4634+
s.tk.MustExec("admin check table gcai_table")
46194635
}
46204636

46214637
func (s *testDBSuite) TestModifyColumnCharset(c *C) {

ddl/index.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ func mergeAddIndexCtxToResult(taskCtx *addIndexTaskContext, result *addIndexResu
519519

520520
func newAddIndexWorker(sessCtx sessionctx.Context, worker *worker, id int, t table.PhysicalTable, indexInfo *model.IndexInfo, decodeColMap map[int64]decoder.Column) *addIndexWorker {
521521
index := tables.NewIndex(t.GetPhysicalID(), t.Meta(), indexInfo)
522-
rowDecoder := decoder.NewRowDecoder(t.Cols(), decodeColMap)
522+
rowDecoder := decoder.NewRowDecoder(t, decodeColMap)
523523
return &addIndexWorker{
524524
id: id,
525525
ddlWorker: worker,
@@ -549,7 +549,7 @@ func (w *addIndexWorker) getIndexRecord(handle int64, recordKey []byte, rawRecor
549549
cols := t.Cols()
550550
idxInfo := w.index.Meta()
551551
sysZone := timeutil.SystemLocation()
552-
_, err := w.rowDecoder.DecodeAndEvalRowWithMap(w.sessCtx, rawRecord, time.UTC, sysZone, w.rowMap)
552+
_, err := w.rowDecoder.DecodeAndEvalRowWithMap(w.sessCtx, handle, rawRecord, time.UTC, sysZone, w.rowMap)
553553
if err != nil {
554554
return nil, errors.Trace(errCantDecodeIndex.GenWithStackByArgs(err))
555555
}

executor/admin_test.go

Lines changed: 127 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,10 @@ func (s *testSuite) TestAdminRecoverIndex(c *C) {
101101
c.Assert(err, IsNil)
102102
err = txn.Commit(context.Background())
103103
c.Assert(err, IsNil)
104-
_, err = tk.Exec("admin check table admin_test")
104+
err = tk.ExecToErr("admin check table admin_test")
105105
c.Assert(err, NotNil)
106106
c.Assert(executor.ErrAdminCheckTable.Equal(err), IsTrue)
107-
_, err = tk.Exec("admin check index admin_test c2")
107+
err = tk.ExecToErr("admin check index admin_test c2")
108108
c.Assert(err, NotNil)
109109

110110
r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
@@ -125,7 +125,7 @@ func (s *testSuite) TestAdminRecoverIndex(c *C) {
125125
err = txn.Commit(context.Background())
126126
c.Assert(err, IsNil)
127127

128-
_, err = tk.Exec("admin check index admin_test c2")
128+
err = tk.ExecToErr("admin check index admin_test c2")
129129
c.Assert(err, NotNil)
130130
r = tk.MustQuery("admin recover index admin_test c2")
131131
r.Check(testkit.Rows("1 5"))
@@ -147,9 +147,9 @@ func (s *testSuite) TestAdminRecoverIndex(c *C) {
147147
err = txn.Commit(context.Background())
148148
c.Assert(err, IsNil)
149149

150-
_, err = tk.Exec("admin check table admin_test")
150+
err = tk.ExecToErr("admin check table admin_test")
151151
c.Assert(err, NotNil)
152-
_, err = tk.Exec("admin check index admin_test c2")
152+
err = tk.ExecToErr("admin check index admin_test c2")
153153
c.Assert(err, NotNil)
154154

155155
r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
@@ -271,9 +271,9 @@ func (s *testSuite) TestAdminCleanupIndex(c *C) {
271271
err = txn.Commit(context.Background())
272272
c.Assert(err, IsNil)
273273

274-
_, err = tk.Exec("admin check table admin_test")
274+
err = tk.ExecToErr("admin check table admin_test")
275275
c.Assert(err, NotNil)
276-
_, err = tk.Exec("admin check index admin_test c2")
276+
err = tk.ExecToErr("admin check index admin_test c2")
277277
c.Assert(err, NotNil)
278278
r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
279279
r.Check(testkit.Rows("11"))
@@ -283,9 +283,9 @@ func (s *testSuite) TestAdminCleanupIndex(c *C) {
283283
r.Check(testkit.Rows("6"))
284284
tk.MustExec("admin check index admin_test c2")
285285

286-
_, err = tk.Exec("admin check table admin_test")
286+
err = tk.ExecToErr("admin check table admin_test")
287287
c.Assert(err, NotNil)
288-
_, err = tk.Exec("admin check index admin_test c3")
288+
err = tk.ExecToErr("admin check index admin_test c3")
289289
c.Assert(err, NotNil)
290290
r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c3)")
291291
r.Check(testkit.Rows("9"))
@@ -332,9 +332,9 @@ func (s *testSuite) TestAdminCleanupIndexPKNotHandle(c *C) {
332332
err = txn.Commit(context.Background())
333333
c.Assert(err, IsNil)
334334

335-
_, err = tk.Exec("admin check table admin_test")
335+
err = tk.ExecToErr("admin check table admin_test")
336336
c.Assert(err, NotNil)
337-
_, err = tk.Exec("admin check index admin_test `primary`")
337+
err = tk.ExecToErr("admin check index admin_test `primary`")
338338
c.Assert(err, NotNil)
339339
r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(`primary`)")
340340
r.Check(testkit.Rows("6"))
@@ -384,11 +384,11 @@ func (s *testSuite) TestAdminCleanupIndexMore(c *C) {
384384
err = txn.Commit(context.Background())
385385
c.Assert(err, IsNil)
386386

387-
_, err = tk.Exec("admin check table admin_test")
387+
err = tk.ExecToErr("admin check table admin_test")
388388
c.Assert(err, NotNil)
389-
_, err = tk.Exec("admin check index admin_test c1")
389+
err = tk.ExecToErr("admin check index admin_test c1")
390390
c.Assert(err, NotNil)
391-
_, err = tk.Exec("admin check index admin_test c2")
391+
err = tk.ExecToErr("admin check index admin_test c2")
392392
c.Assert(err, NotNil)
393393
r := tk.MustQuery("SELECT COUNT(*) FROM admin_test")
394394
r.Check(testkit.Rows("3"))
@@ -409,6 +409,112 @@ func (s *testSuite) TestAdminCleanupIndexMore(c *C) {
409409
tk.MustExec("admin check table admin_test")
410410
}
411411

412+
func (s *testSuite) TestAdminCheckTableFailed(c *C) {
413+
tk := testkit.NewTestKit(c, s.store)
414+
tk.MustExec("use test")
415+
tk.MustExec("drop table if exists admin_test")
416+
tk.MustExec("create table admin_test (c1 int, c2 int, c3 varchar(255) default '1', primary key(c1), key(c3), unique key(c2), key(c2, c3))")
417+
tk.MustExec("insert admin_test (c1, c2, c3) values (-10, -20, 'y'), (-1, -10, 'z'), (1, 11, 'a'), (2, 12, 'b'), (5, 15, 'c'), (10, 20, 'd'), (20, 30, 'e')")
418+
419+
// Make some corrupted index. Build the index information.
420+
s.ctx = mock.NewContext()
421+
s.ctx.Store = s.store
422+
is := s.domain.InfoSchema()
423+
dbName := model.NewCIStr("test")
424+
tblName := model.NewCIStr("admin_test")
425+
tbl, err := is.TableByName(dbName, tblName)
426+
c.Assert(err, IsNil)
427+
tblInfo := tbl.Meta()
428+
idxInfo := tblInfo.Indices[1]
429+
indexOpr := tables.NewIndex(tblInfo.ID, tblInfo, idxInfo)
430+
sc := s.ctx.GetSessionVars().StmtCtx
431+
tk.Se.GetSessionVars().IndexLookupSize = 3
432+
tk.Se.GetSessionVars().MaxChunkSize = 3
433+
434+
// Reduce one row of index.
435+
// Table count > index count.
436+
// Index c2 is missing 11.
437+
txn, err := s.store.Begin()
438+
c.Assert(err, IsNil)
439+
err = indexOpr.Delete(sc, txn, types.MakeDatums(-10), -1)
440+
c.Assert(err, IsNil)
441+
err = txn.Commit(context.Background())
442+
c.Assert(err, IsNil)
443+
err = tk.ExecToErr("admin check table admin_test")
444+
c.Assert(err.Error(), Equals,
445+
"[executor:8003]admin_test err:[admin:1]index:<nil> != record:&admin.RecordData{Handle:-1, Values:[]types.Datum{types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:-10, b:[]uint8(nil), x:interface {}(nil)}}}")
446+
c.Assert(executor.ErrAdminCheckTable.Equal(err), IsTrue)
447+
r := tk.MustQuery("admin recover index admin_test c2")
448+
r.Check(testkit.Rows("1 7"))
449+
tk.MustExec("admin check table admin_test")
450+
451+
// Add one row of index.
452+
// Table count < index count.
453+
// Index c2 has one more values ​​than table data: 0, and the handle 0 hasn't correlative record.
454+
txn, err = s.store.Begin()
455+
c.Assert(err, IsNil)
456+
_, err = indexOpr.Create(s.ctx, txn, types.MakeDatums(0), 0)
457+
c.Assert(err, IsNil)
458+
err = txn.Commit(context.Background())
459+
c.Assert(err, IsNil)
460+
err = tk.ExecToErr("admin check table admin_test")
461+
c.Assert(err.Error(), Equals, "handle 0, index:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:0, b:[]uint8(nil), x:interface {}(nil)} != record:<nil>")
462+
463+
// Add one row of index.
464+
// Table count < index count.
465+
// Index c2 has two more values ​​than table data: 10, 13, and these handles have correlative record.
466+
txn, err = s.store.Begin()
467+
c.Assert(err, IsNil)
468+
err = indexOpr.Delete(sc, txn, types.MakeDatums(0), 0)
469+
c.Assert(err, IsNil)
470+
// Make sure the index value "19" is smaller "21". Then we scan to "19" before "21".
471+
_, err = indexOpr.Create(s.ctx, txn, types.MakeDatums(19), 10)
472+
c.Assert(err, IsNil)
473+
_, err = indexOpr.Create(s.ctx, txn, types.MakeDatums(13), 2)
474+
c.Assert(err, IsNil)
475+
err = txn.Commit(context.Background())
476+
c.Assert(err, IsNil)
477+
err = tk.ExecToErr("admin check table admin_test")
478+
c.Assert(err.Error(), Equals, "col c2, handle 2, index:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:13, b:[]uint8(nil), x:interface {}(nil)} != record:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:12, b:[]uint8(nil), x:interface {}(nil)}")
479+
480+
// Table count = index count.
481+
// Two indices have the same handle.
482+
txn, err = s.store.Begin()
483+
c.Assert(err, IsNil)
484+
err = indexOpr.Delete(sc, txn, types.MakeDatums(13), 2)
485+
c.Assert(err, IsNil)
486+
err = indexOpr.Delete(sc, txn, types.MakeDatums(12), 2)
487+
c.Assert(err, IsNil)
488+
err = txn.Commit(context.Background())
489+
c.Assert(err, IsNil)
490+
err = tk.ExecToErr("admin check table admin_test")
491+
c.Assert(err.Error(), Equals, "col c2, handle 10, index:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:19, b:[]uint8(nil), x:interface {}(nil)} != record:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:20, b:[]uint8(nil), x:interface {}(nil)}")
492+
493+
// Table count = index count.
494+
// Index c2 has one line of data is 19, the corresponding table data is 20.
495+
txn, err = s.store.Begin()
496+
c.Assert(err, IsNil)
497+
_, err = indexOpr.Create(s.ctx, txn, types.MakeDatums(12), 2)
498+
c.Assert(err, IsNil)
499+
err = indexOpr.Delete(sc, txn, types.MakeDatums(20), 10)
500+
c.Assert(err, IsNil)
501+
err = txn.Commit(context.Background())
502+
c.Assert(err, IsNil)
503+
err = tk.ExecToErr("admin check table admin_test")
504+
c.Assert(err.Error(), Equals, "col c2, handle 10, index:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:19, b:[]uint8(nil), x:interface {}(nil)} != record:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:20, b:[]uint8(nil), x:interface {}(nil)}")
505+
506+
// Recover records.
507+
txn, err = s.store.Begin()
508+
c.Assert(err, IsNil)
509+
err = indexOpr.Delete(sc, txn, types.MakeDatums(19), 10)
510+
c.Assert(err, IsNil)
511+
_, err = indexOpr.Create(s.ctx, txn, types.MakeDatums(20), 10)
512+
c.Assert(err, IsNil)
513+
err = txn.Commit(context.Background())
514+
c.Assert(err, IsNil)
515+
tk.MustExec("admin check table admin_test")
516+
}
517+
412518
func (s *testSuite) TestAdminCheckTable(c *C) {
413519
// test NULL value.
414520
tk := testkit.NewTestKit(c, s.store)
@@ -466,22 +572,22 @@ func (s *testSuite) TestAdminCheckTable(c *C) {
466572

467573
// Test index in virtual generated column.
468574
tk.MustExec(`drop table if exists test`)
469-
tk.MustExec(`create table test ( b json , c int as (JSON_EXTRACT(b,'$.d')) , index idxc(c));`)
575+
tk.MustExec(`create table test ( b json , c int as (JSON_EXTRACT(b,'$.d')), index idxc(c));`)
470576
tk.MustExec(`INSERT INTO test set b='{"d": 100}';`)
471577
tk.MustExec(`admin check table test;`)
472578
// Test prefix index.
473579
tk.MustExec(`drop table if exists t`)
474580
tk.MustExec(`CREATE TABLE t (
475-
ID CHAR(32) NOT NULL,
476-
name CHAR(32) NOT NULL,
477-
value CHAR(255),
478-
INDEX indexIDname (ID(8),name(8)));`)
581+
ID CHAR(32) NOT NULL,
582+
name CHAR(32) NOT NULL,
583+
value CHAR(255),
584+
INDEX indexIDname (ID(8),name(8)));`)
479585
tk.MustExec(`INSERT INTO t VALUES ('keyword','urlprefix','text/ /text');`)
480586
tk.MustExec(`admin check table t;`)
481587

482588
tk.MustExec("use mysql")
483589
tk.MustExec(`admin check table test.t;`)
484-
_, err := tk.Exec("admin check table t")
590+
err := tk.ExecToErr("admin check table t")
485591
c.Assert(err, NotNil)
486592

487593
// test add index on time type column which have default value
@@ -521,7 +627,7 @@ func (s *testSuite) TestAdminCheckTable(c *C) {
521627
tk.MustExec(`drop table if exists t1`)
522628
tk.MustExec(`create table t1 (a decimal(2,1), index(a))`)
523629
tk.MustExec(`insert into t1 set a='1.9'`)
524-
_, err = tk.Exec(`alter table t1 modify column a decimal(3,2);`)
630+
err = tk.ExecToErr(`alter table t1 modify column a decimal(3,2);`)
525631
c.Assert(err, NotNil)
526632
c.Assert(err.Error(), Equals, "[ddl:203]unsupported modify decimal column precision")
527633
tk.MustExec(`delete from t1;`)

executor/builder.go

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,8 @@ func (b *executorBuilder) buildCheckIndex(v *plannercore.CheckIndex) Executor {
271271
b.err = errors.Trace(err)
272272
return nil
273273
}
274-
readerExec.ranges = ranger.FullRange()
275-
readerExec.isCheckOp = true
274+
275+
buildIndexLookUpChecker(b, v.IndexLookUpReader, readerExec)
276276

277277
e := &CheckIndexExec{
278278
baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ExplainID()),
@@ -285,12 +285,59 @@ func (b *executorBuilder) buildCheckIndex(v *plannercore.CheckIndex) Executor {
285285
return e
286286
}
287287

288+
// buildIndexLookUpChecker builds check information to IndexLookUpReader.
289+
func buildIndexLookUpChecker(b *executorBuilder, readerPlan *plannercore.PhysicalIndexLookUpReader,
290+
readerExec *IndexLookUpExecutor) {
291+
is := readerPlan.IndexPlans[0].(*plannercore.PhysicalIndexScan)
292+
readerExec.dagPB.OutputOffsets = make([]uint32, 0, len(is.Index.Columns))
293+
for i := 0; i <= len(is.Index.Columns); i++ {
294+
readerExec.dagPB.OutputOffsets = append(readerExec.dagPB.OutputOffsets, uint32(i))
295+
}
296+
readerExec.ranges = ranger.FullRange()
297+
ts := readerPlan.TablePlans[0].(*plannercore.PhysicalTableScan)
298+
readerExec.handleIdx = ts.HandleIdx
299+
300+
tps := make([]*types.FieldType, 0, len(is.Columns)+1)
301+
for _, col := range is.Columns {
302+
tps = append(tps, &col.FieldType)
303+
}
304+
tps = append(tps, types.NewFieldType(mysql.TypeLonglong))
305+
readerExec.checkIndexValue = &checkIndexValue{genExprs: is.GenExprs, idxColTps: tps}
306+
307+
colNames := make([]string, 0, len(is.Columns))
308+
for _, col := range is.Columns {
309+
colNames = append(colNames, col.Name.O)
310+
}
311+
var err error
312+
readerExec.idxTblCols, err = table.FindCols(readerExec.table.Cols(), colNames, true)
313+
if err != nil {
314+
b.err = errors.Trace(err)
315+
return
316+
}
317+
}
318+
288319
func (b *executorBuilder) buildCheckTable(v *plannercore.CheckTable) Executor {
320+
readerExecs := make([]*IndexLookUpExecutor, 0, len(v.IndexLookUpReaders))
321+
for _, readerPlan := range v.IndexLookUpReaders {
322+
readerExec, err := buildNoRangeIndexLookUpReader(b, readerPlan)
323+
if err != nil {
324+
b.err = errors.Trace(err)
325+
return nil
326+
}
327+
buildIndexLookUpChecker(b, readerPlan, readerExec)
328+
329+
readerExecs = append(readerExecs, readerExec)
330+
}
331+
289332
e := &CheckTableExec{
290333
baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ExplainID()),
291-
tables: v.Tables,
334+
dbName: v.DBName,
335+
tblInfo: v.TblInfo,
336+
indices: v.Indices,
292337
is: b.is,
293-
genExprs: v.GenExprs,
338+
srcs: readerExecs,
339+
exitCh: make(chan struct{}),
340+
retCh: make(chan error, len(v.Indices)),
294341
}
295342
return e
296343
}

0 commit comments

Comments
 (0)