Skip to content

Commit

Permalink
*: support show stats_extended to inspect extended stats cache (#23052
Browse files Browse the repository at this point in the history
)
  • Loading branch information
eurekaka authored Mar 3, 2021
1 parent b81e547 commit 93c1779
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 1 deletion.
2 changes: 2 additions & 0 deletions executor/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ func (e *ShowExec) fetchAll(ctx context.Context) error {
return e.fetchShowProcessList()
case ast.ShowEvents:
// empty result
case ast.ShowStatsExtended:
return e.fetchShowStatsExtended()
case ast.ShowStatsMeta:
return e.fetchShowStatsMeta()
case ast.ShowStatsHistograms:
Expand Down
71 changes: 71 additions & 0 deletions executor/show_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,88 @@
package executor

import (
"fmt"
"sort"
"strings"
"time"

"github.com/pingcap/errors"
"github.com/pingcap/parser/ast"
"github.com/pingcap/parser/model"
"github.com/pingcap/parser/mysql"
"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/statistics"
"github.com/pingcap/tidb/store/tikv/oracle"
"github.com/pingcap/tidb/types"
)

func (e *ShowExec) fetchShowStatsExtended() error {
do := domain.GetDomain(e.ctx)
h := do.StatsHandle()
dbs := do.InfoSchema().AllSchemas()
for _, db := range dbs {
for _, tblInfo := range db.Tables {
pi := tblInfo.GetPartitionInfo()
// Extended statistics for partitioned table is not supported now.
if pi != nil {
continue
}
e.appendTableForStatsExtended(db.Name.L, tblInfo, h.GetTableStats(tblInfo))
}
}
return nil
}

func (e *ShowExec) appendTableForStatsExtended(dbName string, tbl *model.TableInfo, statsTbl *statistics.Table) {
if statsTbl.Pseudo || statsTbl.ExtendedStats == nil || len(statsTbl.ExtendedStats.Stats) == 0 {
return
}
colID2Name := make(map[int64]string, len(tbl.Columns))
for _, col := range tbl.Columns {
colID2Name[col.ID] = col.Name.L
}
var sb strings.Builder
for statsName, item := range statsTbl.ExtendedStats.Stats {
sb.WriteString("[")
for i, colID := range item.ColIDs {
name, ok := colID2Name[colID]
if ok {
sb.WriteString(name)
} else {
sb.WriteString("?")
}
if i != len(item.ColIDs)-1 {
sb.WriteString(",")
}
}
sb.WriteString("]")
colNames := sb.String()
sb.Reset()
var statsType, statsVal string
switch item.Tp {
case ast.StatsTypeCorrelation:
statsType = "correlation"
statsVal = fmt.Sprintf("%f", item.ScalarVals)
case ast.StatsTypeDependency:
statsType = "dependency"
statsVal = item.StringVals
case ast.StatsTypeCardinality:
statsType = "cardinality"
statsVal = item.StringVals
}
e.appendRow([]interface{}{
dbName,
tbl.Name.L,
statsName,
colNames,
statsType,
statsVal,
// Same LastUpdateVersion for records of the same table, mainly for debug purpose on product env.
statsTbl.ExtendedStats.LastUpdateVersion,
})
}
}

func (e *ShowExec) fetchShowStatsMeta() error {
do := domain.GetDomain(e.ctx)
h := do.StatsHandle()
Expand Down
50 changes: 50 additions & 0 deletions executor/show_stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,53 @@ func (s *testShowStatsSuite) TestShowStatusSnapshot(c *C) {
result := tk.MustQuery("show table status;")
c.Check(result.Rows()[0][0], Matches, "t")
}

func (s *testShowStatsSuite) TestShowStatsExtended(c *C) {
tk := testkit.NewTestKit(c, s.store)
s.domain.StatsHandle().Clear()
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int, b int, c int)")
tk.MustExec("insert into t values(1,1,3),(2,2,2),(3,3,1)")

tk.MustExec("set session tidb_enable_extended_stats = on")
tk.MustExec("alter table t add stats_extended s1 correlation(a,b)")
tk.MustExec("alter table t add stats_extended s2 correlation(a,c)")
tk.MustQuery("select name, status from mysql.stats_extended where name like 's%'").Sort().Check(testkit.Rows(
"s1 0",
"s2 0",
))
result := tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'")
c.Assert(len(result.Rows()), Equals, 0)

tk.MustExec("analyze table t")
tk.MustQuery("select name, status from mysql.stats_extended where name like 's%'").Sort().Check(testkit.Rows(
"s1 1",
"s2 1",
))
result = tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'").Sort()
c.Assert(len(result.Rows()), Equals, 2)
c.Assert(result.Rows()[0][0], Equals, "test")
c.Assert(result.Rows()[0][1], Equals, "t")
c.Assert(result.Rows()[0][2], Equals, "s1")
c.Assert(result.Rows()[0][3], Equals, "[a,b]")
c.Assert(result.Rows()[0][4], Equals, "correlation")
c.Assert(result.Rows()[0][5], Equals, "1.000000")
c.Assert(result.Rows()[1][0], Equals, "test")
c.Assert(result.Rows()[1][1], Equals, "t")
c.Assert(result.Rows()[1][2], Equals, "s2")
c.Assert(result.Rows()[1][3], Equals, "[a,c]")
c.Assert(result.Rows()[1][4], Equals, "correlation")
c.Assert(result.Rows()[1][5], Equals, "-1.000000")
c.Assert(result.Rows()[1][6], Equals, result.Rows()[0][6])

tk.MustExec("alter table t drop stats_extended s1")
tk.MustExec("alter table t drop stats_extended s2")
tk.MustQuery("select name, status from mysql.stats_extended where name like 's%'").Sort().Check(testkit.Rows(
"s1 2",
"s2 2",
))
s.domain.StatsHandle().Update(s.domain.InfoSchema())
result = tk.MustQuery("show stats_extended where db_name = 'test' and table_name = 't'")
c.Assert(len(result.Rows()), Equals, 0)
}
5 changes: 4 additions & 1 deletion planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2142,7 +2142,7 @@ func (b *PlanBuilder) buildShow(ctx context.Context, show *ast.ShowStmt) (Plan,
p.setSchemaAndNames(buildShowNextRowID())
b.visitInfo = appendVisitInfo(b.visitInfo, mysql.SelectPriv, show.Table.Schema.L, show.Table.Name.L, "", ErrPrivilegeCheckFail)
return p, nil
case ast.ShowStatsBuckets, ast.ShowStatsHistograms, ast.ShowStatsMeta, ast.ShowStatsHealthy, ast.ShowStatsTopN:
case ast.ShowStatsBuckets, ast.ShowStatsHistograms, ast.ShowStatsMeta, ast.ShowStatsExtended, ast.ShowStatsHealthy, ast.ShowStatsTopN:
user := b.ctx.GetSessionVars().User
var err error
if user != nil {
Expand Down Expand Up @@ -3663,6 +3663,9 @@ func buildShowSchema(s *ast.ShowStmt, isView bool, isSequence bool) (schema *exp
case ast.ShowStatsMeta:
names = []string{"Db_name", "Table_name", "Partition_name", "Update_time", "Modify_count", "Row_count"}
ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeDatetime, mysql.TypeLonglong, mysql.TypeLonglong}
case ast.ShowStatsExtended:
names = []string{"Db_name", "Table_name", "Stats_name", "Column_names", "Stats_type", "Stats_val", "Last_update_version"}
ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong}
case ast.ShowStatsHistograms:
names = []string{"Db_name", "Table_name", "Partition_name", "Column_name", "Is_index", "Update_time", "Distinct_count", "Null_count", "Avg_col_size", "Correlation"}
ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeTiny, mysql.TypeDatetime,
Expand Down

0 comments on commit 93c1779

Please sign in to comment.