From 058a928695980963d232be6a55cb5dbed304c3ff Mon Sep 17 00:00:00 2001 From: crazycs520 Date: Thu, 29 Aug 2019 13:14:26 +0800 Subject: [PATCH] executor: split a separate region for index when split table region (#11721) --- executor/executor_test.go | 31 ++++++++++++++++++------------- executor/split.go | 17 +++++++++++++++++ planner/core/planbuilder.go | 2 +- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/executor/executor_test.go b/executor/executor_test.go index 4cde3db1d40b5..ee6b0e023c09b 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -3746,29 +3746,28 @@ func (h *oomCapturer) Check(e zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore. func (s *testSuite) TestShowTableRegion(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") - tk.MustExec("drop table if exists t_regions1, t_regions") - atomic.StoreUint32(&ddl.EnableSplitTableRegion, 0) - tk.MustExec("create table t_regions1 (a int key, b int, index idx(b))") - tk.MustExec("create table t_regions (a int key, b int, index idx(b))") + tk.MustExec("drop table if exists t_regions") + tk.MustExec("create table t_regions (a int key, b int, c int, index idx(b), index idx2(c))") // Test show table regions. - tk.MustExec(`split table t_regions1 by (0)`) - tk.MustQuery(`split table t_regions between (-10000) and (10000) regions 4;`).Check(testkit.Rows("3 1")) + tk.MustQuery(`split table t_regions between (-10000) and (10000) regions 4;`).Check(testkit.Rows("4 1")) re := tk.MustQuery("show table t_regions regions") rows := re.Rows() - // Table t_regions should have 4 regions now. - c.Assert(len(rows), Equals, 4) + // Table t_regions should have 5 regions now. + // 4 regions to store record data. + // 1 region to store index data. + c.Assert(len(rows), Equals, 5) c.Assert(len(rows[0]), Equals, 7) - tbl1 := testGetTableByName(c, tk.Se, "test", "t_regions1") tbl := testGetTableByName(c, tk.Se, "test", "t_regions") // Check the region start key. - c.Assert(rows[0][1], Matches, fmt.Sprintf("t_%d_.*", tbl1.Meta().ID)) + c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_r", tbl.Meta().ID)) c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_-5000", tbl.Meta().ID)) c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_0", tbl.Meta().ID)) c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_5000", tbl.Meta().ID)) + c.Assert(rows[4][2], Equals, fmt.Sprintf("t_%d_r", tbl.Meta().ID)) // Test show table index regions. - tk.MustQuery(`split table t_regions index idx between (-1000) and (1000) regions 4;`).Check(testkit.Rows("4 1")) + tk.MustQuery(`split table t_regions index idx between (-1000) and (1000) regions 4;`).Check(testkit.Rows("5 1")) re = tk.MustQuery("show table t_regions index idx regions") rows = re.Rows() // The index `idx` of table t_regions should have 4 regions now. @@ -3781,15 +3780,21 @@ func (s *testSuite) TestShowTableRegion(c *C) { re = tk.MustQuery("show table t_regions regions") rows = re.Rows() - c.Assert(len(rows), Equals, 7) + // The index `idx` of table t_regions should have 9 regions now. + // 4 regions to store record data. + // 4 region to store index idx data. + // 1 region to store index idx2 data. + c.Assert(len(rows), Equals, 9) // Check the region start key. - c.Assert(rows[0][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) + c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_r", tbl.Meta().ID)) c.Assert(rows[1][1], Equals, fmt.Sprintf("t_%d_r_-5000", tbl.Meta().ID)) c.Assert(rows[2][1], Equals, fmt.Sprintf("t_%d_r_0", tbl.Meta().ID)) c.Assert(rows[3][1], Equals, fmt.Sprintf("t_%d_r_5000", tbl.Meta().ID)) c.Assert(rows[4][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) c.Assert(rows[5][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) c.Assert(rows[6][1], Matches, fmt.Sprintf("t_%d_i_1_.*", tbl.Meta().ID)) + c.Assert(rows[7][2], Equals, fmt.Sprintf("t_%d_i_2_", tbl.Meta().ID)) + c.Assert(rows[8][2], Equals, fmt.Sprintf("t_%d_r", tbl.Meta().ID)) // Test unsigned primary key and wait scatter finish. tk.MustExec("drop table if exists t_regions") diff --git a/executor/split.go b/executor/split.go index a27fd5741b5dc..03cc168e6b20b 100755 --- a/executor/split.go +++ b/executor/split.go @@ -132,6 +132,16 @@ func (e *SplitIndexRegionExec) getSplitIdxKeys() ([][]byte, error) { startIdxKey := tablecodec.EncodeTableIndexPrefix(e.tableInfo.ID, e.indexInfo.ID) idxKeys = append(idxKeys, startIdxKey) + // Split in the end for the other index key. + for _, idx := range e.tableInfo.Indices { + if idx.ID <= e.indexInfo.ID { + continue + } + endIdxKey := tablecodec.EncodeTableIndexPrefix(e.tableInfo.ID, idx.ID) + idxKeys = append(idxKeys, endIdxKey) + break + } + index := tables.NewIndex(e.tableInfo.ID, e.tableInfo, e.indexInfo) // Split index regions by user specified value lists. if len(e.valueLists) > 0 { @@ -415,6 +425,10 @@ func (e *SplitTableRegionExec) getSplitTableKeys() ([][]byte, error) { return nil, errors.Errorf("Split table `%s` region step value should more than %v, step %v is invalid", e.tableInfo.Name, minRegionStepValue, step) } + // Split a separate region for index. + if len(e.tableInfo.Indices) > 0 { + keys = append(keys, recordPrefix) + } recordID := lowerValue for i := 1; i < e.num; i++ { recordID += int64(step) @@ -539,6 +553,9 @@ func (d *regionKeyDecoder) decodeRegionKey(key []byte) string { if len(d.indexPrefix) > 0 && bytes.HasPrefix(key, d.indexPrefix) { return fmt.Sprintf("t_%d_i_%d_%x", d.physicalTableID, d.indexID, key[len(d.indexPrefix):]) } else if len(d.recordPrefix) > 0 && bytes.HasPrefix(key, d.recordPrefix) { + if len(d.recordPrefix) == len(key) { + return fmt.Sprintf("t_%d_r", d.physicalTableID) + } _, handle, err := codec.DecodeInt(key[len(d.recordPrefix):]) if err == nil { return fmt.Sprintf("t_%d_r_%d", d.physicalTableID, handle) diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 107035efc2e9a..871eef3538964 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -966,7 +966,7 @@ func buildTableRegionsSchema() *expression.Schema { schema := expression.NewSchema(make([]*expression.Column, 0, 10)...) schema.Append(buildColumn("", "REGION_ID", mysql.TypeLonglong, 4)) schema.Append(buildColumn("", "START_KEY", mysql.TypeVarchar, 64)) - schema.Append(buildColumn("", "END_Key", mysql.TypeVarchar, 64)) + schema.Append(buildColumn("", "END_KEY", mysql.TypeVarchar, 64)) schema.Append(buildColumn("", "LEADER_ID", mysql.TypeLonglong, 4)) schema.Append(buildColumn("", "LEADER_STORE_ID", mysql.TypeLonglong, 4)) schema.Append(buildColumn("", "PEERS", mysql.TypeVarchar, 64))