Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*: speed up the operation of "admin check table" #8572

Merged
merged 36 commits into from
Jul 31, 2019
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
48d831f
*: speed up "admin check table"
zimulala Sep 11, 2018
4c1d0fb
Merge branch 'master' into zimuxia/check-table
zimulala Nov 26, 2018
25f85a2
*: update
zimulala Nov 26, 2018
7e2bf6f
*: add logs
zimulala Nov 28, 2018
a7785e8
*: add logs
zimulala Nov 28, 2018
e7c6392
executor: tiny update
zimulala Nov 30, 2018
9c324e9
*: update
zimulala Dec 3, 2018
0a590ab
*: add tests
zimulala Dec 4, 2018
a5e0cc0
Merge branch 'master' into check-table-1
zimulala Dec 4, 2018
dc8fbd6
executor: tiny update tests
zimulala Dec 4, 2018
424d42d
Merge branch 'master' into check-table-1
zimulala Dec 4, 2018
271c12b
*: update
zimulala Dec 4, 2018
41c753c
executor: make fmt happy
zimulala Dec 5, 2018
bb42b3d
util/admin: make lint happy
zimulala Dec 5, 2018
719c55d
Merge branch 'master' into check-table-1
zimulala Dec 11, 2018
a7dedb4
Merge branch 'master' into check-table-1
zimulala Dec 11, 2018
83e019c
util/admin: fix data race
zimulala Dec 11, 2018
63c99ff
util/admin: fix DATA RACE
zimulala Dec 11, 2018
39ab605
executor, util: address comments
zimulala Dec 17, 2018
af99cc1
Merge branch 'master' into check-table-1
zimulala Jan 25, 2019
a7a37c2
Merge branch 'master' into check-table-1
zimulala Jan 27, 2019
7b02d68
Merge branch 'master' into check-table-1
zimulala Jul 4, 2019
89fb60a
*: check the index values
zimulala Jul 8, 2019
10cb5b0
executor, planner: remove logs
zimulala Jul 15, 2019
dd72622
*: remove logs
zimulala Jul 15, 2019
697c31a
*: update comments and address comments
zimulala Jul 22, 2019
6a21c98
Merge branch 'master' into check-table-1
zimulala Jul 22, 2019
992527a
executor: clean up and address comments
zimulala Jul 24, 2019
9f1d27d
planner, executor: remove possible the PK column
zimulala Jul 26, 2019
cbf4ba7
Merge branch 'master' into check-table-1
zimulala Jul 26, 2019
2c7d2d2
*: add concurrency limit and address comments
zimulala Jul 30, 2019
da93039
Merge branch 'master' into check-table-1
zimulala Jul 30, 2019
d0fb55c
executor: address comments
zimulala Jul 31, 2019
61ab6a7
executor: address comments
zimulala Jul 31, 2019
21b336b
Merge branch 'master' into check-table-1
sre-bot Jul 31, 2019
1b3645e
Merge branch 'master' into check-table-1
zimulala Jul 31, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 111 additions & 5 deletions executor/admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,112 @@ func (s *testSuite2) TestAdminCleanupIndexMore(c *C) {
tk.MustExec("admin check table admin_test")
}

func (s *testSuite2) TestAdminCheckTableFailed(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists admin_test")
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))")
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')")

// Make some corrupted index. Build the index information.
s.ctx = mock.NewContext()
s.ctx.Store = s.store
is := s.domain.InfoSchema()
dbName := model.NewCIStr("test")
tblName := model.NewCIStr("admin_test")
tbl, err := is.TableByName(dbName, tblName)
c.Assert(err, IsNil)
tblInfo := tbl.Meta()
idxInfo := tblInfo.Indices[1]
indexOpr := tables.NewIndex(tblInfo.ID, tblInfo, idxInfo)
sc := s.ctx.GetSessionVars().StmtCtx
tk.Se.GetSessionVars().IndexLookupSize = 3
tk.Se.GetSessionVars().MaxChunkSize = 3

crazycs520 marked this conversation as resolved.
Show resolved Hide resolved
// Reduce one row of index.
// Table count > index count.
// Index c2 is missing 11.
txn, err := s.store.Begin()
c.Assert(err, IsNil)
err = indexOpr.Delete(sc, txn, types.MakeDatums(-10), -1, nil)
c.Assert(err, IsNil)
err = txn.Commit(context.Background())
c.Assert(err, IsNil)
_, err = tk.Exec("admin check table admin_test")
c.Assert(err.Error(), Equals,
"[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)}}}")
c.Assert(executor.ErrAdminCheckTable.Equal(err), IsTrue)
r := tk.MustQuery("admin recover index admin_test c2")
r.Check(testkit.Rows("1 7"))
tk.MustExec("admin check table admin_test")

// Add one row of index.
// Table count < index count.
// Index c2 has one more values ​​than table data: 0, and the handle 0 hasn't correlative record.
txn, err = s.store.Begin()
c.Assert(err, IsNil)
_, err = indexOpr.Create(s.ctx, txn, types.MakeDatums(0), 0)
c.Assert(err, IsNil)
err = txn.Commit(context.Background())
c.Assert(err, IsNil)
_, err = tk.Exec("admin check table admin_test")
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>")

// Add one row of index.
// Table count < index count.
// Index c2 has two more values ​​than table data: 10, 13, and these handles have correlative record.
txn, err = s.store.Begin()
c.Assert(err, IsNil)
err = indexOpr.Delete(sc, txn, types.MakeDatums(0), 0, nil)
c.Assert(err, IsNil)
// Make sure the index value "19" is smaller "21". Then we scan to "19" before "21".
_, err = indexOpr.Create(s.ctx, txn, types.MakeDatums(19), 10)
c.Assert(err, IsNil)
_, err = indexOpr.Create(s.ctx, txn, types.MakeDatums(13), 2)
c.Assert(err, IsNil)
err = txn.Commit(context.Background())
c.Assert(err, IsNil)
_, err = tk.Exec("admin check table admin_test")
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)}")

// Table count = index count.
// Two indices have the same handle.
txn, err = s.store.Begin()
c.Assert(err, IsNil)
err = indexOpr.Delete(sc, txn, types.MakeDatums(13), 2, nil)
c.Assert(err, IsNil)
err = indexOpr.Delete(sc, txn, types.MakeDatums(12), 2, nil)
c.Assert(err, IsNil)
err = txn.Commit(context.Background())
c.Assert(err, IsNil)
_, err = tk.Exec("admin check table admin_test")
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)}")

// Table count = index count.
// Index c2 has one line of data is 19, the corresponding table data is 20.
txn, err = s.store.Begin()
c.Assert(err, IsNil)
_, err = indexOpr.Create(s.ctx, txn, types.MakeDatums(12), 2)
c.Assert(err, IsNil)
err = indexOpr.Delete(sc, txn, types.MakeDatums(20), 10, nil)
c.Assert(err, IsNil)
err = txn.Commit(context.Background())
c.Assert(err, IsNil)
_, err = tk.Exec("admin check table admin_test")
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)}")

// Recover records.
txn, err = s.store.Begin()
c.Assert(err, IsNil)
err = indexOpr.Delete(sc, txn, types.MakeDatums(19), 10, nil)
c.Assert(err, IsNil)
_, err = indexOpr.Create(s.ctx, txn, types.MakeDatums(20), 10)
c.Assert(err, IsNil)
err = txn.Commit(context.Background())
c.Assert(err, IsNil)
tk.MustExec("admin check table admin_test")
}

func (s *testSuite1) TestAdminCheckTable(c *C) {
// test NULL value.
tk := testkit.NewTestKit(c, s.store)
Expand Down Expand Up @@ -455,16 +561,16 @@ func (s *testSuite1) TestAdminCheckTable(c *C) {

// Test index in virtual generated column.
tk.MustExec(`drop table if exists test`)
tk.MustExec(`create table test ( b json , c int as (JSON_EXTRACT(b,'$.d')) , index idxc(c));`)
tk.MustExec(`create table test ( b json , c int as (JSON_EXTRACT(b,'$.d')), index idxc(c));`)
tk.MustExec(`INSERT INTO test set b='{"d": 100}';`)
tk.MustExec(`admin check table test;`)
// Test prefix index.
tk.MustExec(`drop table if exists t`)
tk.MustExec(`CREATE TABLE t (
ID CHAR(32) NOT NULL,
name CHAR(32) NOT NULL,
value CHAR(255),
INDEX indexIDname (ID(8),name(8)));`)
ID CHAR(32) NOT NULL,
name CHAR(32) NOT NULL,
value CHAR(255),
INDEX indexIDname (ID(8),name(8)));`)
tk.MustExec(`INSERT INTO t VALUES ('keyword','urlprefix','text/ /text');`)
tk.MustExec(`admin check table t;`)

Expand Down
58 changes: 54 additions & 4 deletions executor/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,8 @@ func (b *executorBuilder) buildCheckIndex(v *plannercore.CheckIndex) Executor {
b.err = err
return nil
}
readerExec.ranges = ranger.FullRange()
readerExec.isCheckOp = true

buildIndexLookUpChecker(b, v.IndexLookUpReader, readerExec)

e := &CheckIndexExec{
baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ExplainID()),
Expand All @@ -322,12 +322,59 @@ func (b *executorBuilder) buildCheckIndex(v *plannercore.CheckIndex) Executor {
return e
}

// buildIndexLookUpChecker builds check information to IndexLookUpReader.
func buildIndexLookUpChecker(b *executorBuilder, readerPlan *plannercore.PhysicalIndexLookUpReader,
zimulala marked this conversation as resolved.
Show resolved Hide resolved
readerExec *IndexLookUpExecutor) {
is := readerPlan.IndexPlans[0].(*plannercore.PhysicalIndexScan)
readerExec.dagPB.OutputOffsets = make([]uint32, 0, len(is.Index.Columns))
for i := 0; i <= len(is.Index.Columns); i++ {
readerExec.dagPB.OutputOffsets = append(readerExec.dagPB.OutputOffsets, uint32(i))
}
tps := make([]*types.FieldType, 0, len(is.Columns)+1)
for _, col := range is.Columns {
tps = append(tps, &col.FieldType)
}
tps = append(tps, types.NewFieldType(mysql.TypeLonglong))
readerExec.idxColTps = tps
readerExec.idxInfo = readerExec.index

colNames := make([]string, 0, len(is.Columns))
for _, col := range is.Columns {
colNames = append(colNames, col.Name.O)
}

var err error
readerExec.idxTblCols, err = table.FindCols(readerExec.table.Cols(), colNames, true)
if err != nil {
b.err = errors.Trace(err)
return
}
readerExec.isCheckOp = true
readerExec.ranges = ranger.FullRange()
}

func (b *executorBuilder) buildCheckTable(v *plannercore.CheckTable) Executor {
readerExecs := make([]*IndexLookUpExecutor, 0, len(v.IndexLookUpReaders))
for _, readerPlan := range v.IndexLookUpReaders {
readerExec, err := buildNoRangeIndexLookUpReader(b, readerPlan)
if err != nil {
b.err = errors.Trace(err)
return nil
}
buildIndexLookUpChecker(b, readerPlan, readerExec)

readerExecs = append(readerExecs, readerExec)
}

e := &CheckTableExec{
baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ExplainID()),
tables: v.Tables,
dbName: v.DBName,
tblInfo: v.TblInfo,
indices: v.Indices,
is: b.is,
genExprs: v.GenExprs,
srcs: readerExecs,
exitCh: make(chan struct{}),
retCh: make(chan error, len(v.Indices)),
}
return e
}
Expand Down Expand Up @@ -1887,6 +1934,9 @@ func buildNoRangeIndexLookUpReader(b *executorBuilder, v *plannercore.PhysicalIn
idxPlans: v.IndexPlans,
tblPlans: v.TablePlans,
}
// These are used to check the consistency of the index data.
e.genExprs = is.GenExprs
e.handleIdx = ts.HandleIdx

if containsLimit(indexReq.Executors) {
e.feedback = statistics.NewQueryFeedback(0, nil, 0, is.Desc)
Expand Down
Loading