From fbc1d98a5edc5ee9220b14eec0f1d4f9fe2d9912 Mon Sep 17 00:00:00 2001 From: crazycs Date: Fri, 23 Aug 2019 17:04:23 +0800 Subject: [PATCH 1/2] *: add region read/write bytes info and approximate size/keys in show table regions result. --- executor/executor_test.go | 2 +- executor/show.go | 5 ++++ executor/split.go | 56 ++++++++++++++++++++++++++++++------- planner/core/planbuilder.go | 6 +++- store/helper/helper.go | 8 ++++++ util/pdapi/const.go | 9 +++--- 6 files changed, 70 insertions(+), 16 deletions(-) diff --git a/executor/executor_test.go b/executor/executor_test.go index 03dbf294c6f0e..86fd65a0e5279 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -4135,7 +4135,7 @@ func (s *testSuite) TestShowTableRegion(c *C) { // 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) + c.Assert(len(rows[0]), Equals, 11) tbl := testGetTableByName(c, tk.Se, "test", "t_regions") // Check the region start key. c.Assert(rows[0][1], Equals, fmt.Sprintf("t_%d_r", tbl.Meta().ID)) diff --git a/executor/show.go b/executor/show.go index 27969047ef92b..f415fdb2e2939 100644 --- a/executor/show.go +++ b/executor/show.go @@ -1288,5 +1288,10 @@ func (e *ShowExec) fillRegionsToChunk(regions []regionMeta) { } else { e.result.AppendInt64(6, 0) } + + e.result.AppendInt64(7, regions[i].writtenBytes) + e.result.AppendInt64(8, regions[i].readBytes) + e.result.AppendInt64(9, regions[i].approximateSize) + e.result.AppendInt64(10, regions[i].approximateKeys) } } diff --git a/executor/split.go b/executor/split.go index 6a67aaf83d219..90d481dba6d55 100755 --- a/executor/split.go +++ b/executor/split.go @@ -29,6 +29,7 @@ import ( "github.com/pingcap/parser/mysql" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/store/helper" "github.com/pingcap/tidb/store/tikv" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/tablecodec" @@ -439,12 +440,16 @@ func (e *SplitTableRegionExec) getSplitTableKeys() ([][]byte, error) { // RegionMeta contains a region's peer detail type regionMeta struct { - region *metapb.Region - leaderID uint64 - storeID uint64 // storeID is the store ID of the leader region. - start string - end string - scattering bool + region *metapb.Region + leaderID uint64 + storeID uint64 // storeID is the store ID of the leader region. + start string + end string + scattering bool + writtenBytes int64 + readBytes int64 + approximateSize int64 + approximateKeys int64 } func getPhysicalTableRegions(physicalTableID int64, tableInfo *model.TableInfo, tikvStore tikv.Storage, s kv.SplitableStore, uniqueRegionMap map[uint64]struct{}) ([]regionMeta, error) { @@ -460,7 +465,7 @@ func getPhysicalTableRegions(physicalTableID int64, tableInfo *model.TableInfo, } recordPrefix := tablecodec.GenTableRecordPrefix(physicalTableID) tablePrefix := tablecodec.GenTablePrefix(physicalTableID) - recordRegions, err := getRegionMeta(recordRegionMetas, uniqueRegionMap, tablePrefix, recordPrefix, nil, physicalTableID, 0) + recordRegions, err := getRegionMeta(tikvStore, recordRegionMetas, uniqueRegionMap, tablePrefix, recordPrefix, nil, physicalTableID, 0) if err != nil { return nil, err } @@ -477,7 +482,7 @@ func getPhysicalTableRegions(physicalTableID int64, tableInfo *model.TableInfo, return nil, err } indexPrefix := tablecodec.EncodeTableIndexPrefix(physicalTableID, index.ID) - indexRegions, err := getRegionMeta(regionMetas, uniqueRegionMap, tablePrefix, recordPrefix, indexPrefix, physicalTableID, index.ID) + indexRegions, err := getRegionMeta(tikvStore, regionMetas, uniqueRegionMap, tablePrefix, recordPrefix, indexPrefix, physicalTableID, index.ID) if err != nil { return nil, err } @@ -504,7 +509,7 @@ func getPhysicalIndexRegions(physicalTableID int64, indexInfo *model.IndexInfo, recordPrefix := tablecodec.GenTableRecordPrefix(physicalTableID) tablePrefix := tablecodec.GenTablePrefix(physicalTableID) indexPrefix := tablecodec.EncodeTableIndexPrefix(physicalTableID, indexInfo.ID) - indexRegions, err := getRegionMeta(regions, uniqueRegionMap, tablePrefix, recordPrefix, indexPrefix, physicalTableID, indexInfo.ID) + indexRegions, err := getRegionMeta(tikvStore, regions, uniqueRegionMap, tablePrefix, recordPrefix, indexPrefix, physicalTableID, indexInfo.ID) if err != nil { return nil, err } @@ -585,7 +590,7 @@ func (d *regionKeyDecoder) decodeRegionKey(key []byte) string { return fmt.Sprintf("%x", key) } -func getRegionMeta(regionMetas []*tikv.Region, uniqueRegionMap map[uint64]struct{}, tablePrefix, recordPrefix, indexPrefix []byte, physicalTableID, indexID int64) ([]regionMeta, error) { +func getRegionMeta(tikvStore tikv.Storage, regionMetas []*tikv.Region, uniqueRegionMap map[uint64]struct{}, tablePrefix, recordPrefix, indexPrefix []byte, physicalTableID, indexID int64) ([]regionMeta, error) { regions := make([]regionMeta, 0, len(regionMetas)) for _, r := range regionMetas { if _, ok := uniqueRegionMap[r.GetID()]; ok { @@ -598,6 +603,37 @@ func getRegionMeta(regionMetas []*tikv.Region, uniqueRegionMap map[uint64]struct storeID: r.GetLeaderStoreID(), }) } + regions, err := getRegionInfo(tikvStore, regions) + if err != nil { + return regions, err + } decodeRegionsKey(regions, tablePrefix, recordPrefix, indexPrefix, physicalTableID, indexID) return regions, nil } + +func getRegionInfo(store tikv.Storage, regions []regionMeta) ([]regionMeta, error) { + // check pd server exists. + etcd, ok := store.(tikv.EtcdBackend) + if !ok { + return regions, nil + } + pdHosts := etcd.EtcdAddrs() + if len(pdHosts) == 0 { + return regions, nil + } + tikvHelper := &helper.Helper{ + Store: store, + RegionCache: store.GetRegionCache(), + } + for i := range regions { + regionInfo, err := tikvHelper.GetRegionInfoByID(regions[i].region.Id) + if err != nil { + return nil, err + } + regions[i].writtenBytes = regionInfo.WrittenBytes + regions[i].readBytes = regionInfo.ReadBytes + regions[i].approximateSize = regionInfo.ApproximateSize + regions[i].approximateKeys = regionInfo.ApproximateKeys + } + return regions, nil +} diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index bbc6f3399a843..a5ad23350bc19 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -1207,7 +1207,7 @@ func buildShowDDLJobsFields() *expression.Schema { } func buildTableRegionsSchema() *expression.Schema { - schema := expression.NewSchema(make([]*expression.Column, 0, 10)...) + schema := expression.NewSchema(make([]*expression.Column, 0, 11)...) schema.Append(buildColumn("", "REGION_ID", mysql.TypeLonglong, 4)) schema.Append(buildColumn("", "START_KEY", mysql.TypeVarchar, 64)) schema.Append(buildColumn("", "END_KEY", mysql.TypeVarchar, 64)) @@ -1215,6 +1215,10 @@ func buildTableRegionsSchema() *expression.Schema { schema.Append(buildColumn("", "LEADER_STORE_ID", mysql.TypeLonglong, 4)) schema.Append(buildColumn("", "PEERS", mysql.TypeVarchar, 64)) schema.Append(buildColumn("", "SCATTERING", mysql.TypeTiny, 1)) + schema.Append(buildColumn("", "WRITTEN_BYTES", mysql.TypeLonglong, 4)) + schema.Append(buildColumn("", "READ_BYTES", mysql.TypeLonglong, 4)) + schema.Append(buildColumn("", "APPROXIMATE_SIZE", mysql.TypeLonglong, 4)) + schema.Append(buildColumn("", "APPROXIMATE_KEYS", mysql.TypeLonglong, 4)) return schema } diff --git a/store/helper/helper.go b/store/helper/helper.go index cdf2fa473ff5f..7ef5e612777d5 100644 --- a/store/helper/helper.go +++ b/store/helper/helper.go @@ -22,6 +22,7 @@ import ( "math" "net/http" "sort" + "strconv" "strings" "time" @@ -580,6 +581,13 @@ func (h *Helper) GetRegionsInfo() (*RegionsInfo, error) { return ®ionsInfo, err } +// GetRegionInfoByID gets the region information of the region ID by using PD's api. +func (h *Helper) GetRegionInfoByID(regionID uint64) (*RegionInfo, error) { + var regionInfo RegionInfo + err := h.requestPD("GET", pdapi.RegionByID+strconv.FormatUint(regionID, 10), nil, ®ionInfo) + return ®ionInfo, err +} + // request PD API, decode the response body into res func (h *Helper) requestPD(method, uri string, body io.Reader, res interface{}) error { etcd, ok := h.Store.(tikv.EtcdBackend) diff --git a/util/pdapi/const.go b/util/pdapi/const.go index 436784f627245..29d3746e50122 100644 --- a/util/pdapi/const.go +++ b/util/pdapi/const.go @@ -15,8 +15,9 @@ package pdapi // The following constants are the APIs of PD server. const ( - HotRead = "/pd/api/v1/hotspot/regions/read" - HotWrite = "/pd/api/v1/hotspot/regions/write" - Regions = "/pd/api/v1/regions" - Stores = "/pd/api/v1/stores" + HotRead = "/pd/api/v1/hotspot/regions/read" + HotWrite = "/pd/api/v1/hotspot/regions/write" + Regions = "/pd/api/v1/regions" + RegionByID = "/pd/api/v1//region/id/" + Stores = "/pd/api/v1/stores" ) From 63660bedad15030cb15e807be24995962ad6fd1d Mon Sep 17 00:00:00 2001 From: crazycs520 Date: Thu, 29 Aug 2019 11:15:23 +0800 Subject: [PATCH 2/2] address comment --- planner/core/planbuilder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 96ee7ba87ed71..73b2162efe7f6 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -1240,7 +1240,7 @@ func buildTableRegionsSchema() *expression.Schema { schema.Append(buildColumn("", "SCATTERING", mysql.TypeTiny, 1)) schema.Append(buildColumn("", "WRITTEN_BYTES", mysql.TypeLonglong, 4)) schema.Append(buildColumn("", "READ_BYTES", mysql.TypeLonglong, 4)) - schema.Append(buildColumn("", "APPROXIMATE_SIZE", mysql.TypeLonglong, 4)) + schema.Append(buildColumn("", "APPROXIMATE_SIZE(MB)", mysql.TypeLonglong, 4)) schema.Append(buildColumn("", "APPROXIMATE_KEYS", mysql.TypeLonglong, 4)) return schema }