Repository: pingcap/tidb (Go)

Issue:
topsql: add exec count dedicated to sql duration
## Enhancement

At present, our `SQLDuration` is obtained by dividing `DurationSum` by `ExecCount`, but the statistical positions of `DurationSum` and `ExecCount` are different, and there are some deviations in the data results. We need to introduce an additional `DurationCount` dedicated to `Duration` calculation.



Discussion:
/assign



Patch:
diff --git a/go.mod b/go.mod
index 55930d963bf31..6b1b716a16867 100644
--- a/go.mod
+++ b/go.mod
@@ -55,7 +55,7 @@ require (
 	github.com/pingcap/sysutil v0.0.0-20211208032423-041a72e5860d
 	github.com/pingcap/tidb-tools v5.2.2-0.20211019062242-37a8bef2fa17+incompatible
 	github.com/pingcap/tidb/parser v0.0.0-20211011031125-9b13dc409c5e
-	github.com/pingcap/tipb v0.0.0-20211227115224-a06a85f9d2a5
+	github.com/pingcap/tipb v0.0.0-20220107024056-3b91949a18a7
 	github.com/prometheus/client_golang v1.5.1
 	github.com/prometheus/client_model v0.2.0
 	github.com/prometheus/common v0.9.1
diff --git a/go.sum b/go.sum
index bcbd534983fdc..676442d7c1155 100644
--- a/go.sum
+++ b/go.sum
@@ -611,8 +611,8 @@ github.com/pingcap/tidb-dashboard v0.0.0-20211008050453-a25c25809529/go.mod h1:O
 github.com/pingcap/tidb-dashboard v0.0.0-20211107164327-80363dfbe884/go.mod h1:OCXbZTBTIMRcIt0jFsuCakZP+goYRv6IjawKbwLS2TQ=
 github.com/pingcap/tidb-tools v5.2.2-0.20211019062242-37a8bef2fa17+incompatible h1:c7+izmker91NkjkZ6FgTlmD4k1A5FLOAq+li6Ki2/GY=
 github.com/pingcap/tidb-tools v5.2.2-0.20211019062242-37a8bef2fa17+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM=
-github.com/pingcap/tipb v0.0.0-20211227115224-a06a85f9d2a5 h1:oKL5kSHoQAI9o6mdbxU0cB7fvqm9KyXZs9s/p0kZRnY=
-github.com/pingcap/tipb v0.0.0-20211227115224-a06a85f9d2a5/go.mod h1:A7mrd7WHBl1o63LE2bIBGEJMTNWXqhgmYiOvMLxozfs=
+github.com/pingcap/tipb v0.0.0-20220107024056-3b91949a18a7 h1:DHU4vw0o15qdKsf7d/Pyhun4YtX8FwoDQxG0plPByUg=
+github.com/pingcap/tipb v0.0.0-20220107024056-3b91949a18a7/go.mod h1:A7mrd7WHBl1o63LE2bIBGEJMTNWXqhgmYiOvMLxozfs=
 github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=
 github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
diff --git a/util/topsql/reporter/datamodel.go b/util/topsql/reporter/datamodel.go
index c03e41724b481..cb294e2dd217b 100644
--- a/util/topsql/reporter/datamodel.go
+++ b/util/topsql/reporter/datamodel.go
@@ -89,6 +89,7 @@ func (i *tsItem) toProto() *tipb.TopSQLRecordItem {
 		StmtExecCount:     i.stmtStats.ExecCount,
 		StmtKvExecCount:   i.stmtStats.KvStatsItem.KvExecCount,
 		StmtDurationSumNs: i.stmtStats.SumDurationNs,
+		StmtDurationCount: i.stmtStats.DurationCount,
 		// Convert more indicators here.
 	}
 }
diff --git a/util/topsql/stmtstats/stmtstats.go b/util/topsql/stmtstats/stmtstats.go
index 8ad5ab1c7b883..e2dee3df20459 100644
--- a/util/topsql/stmtstats/stmtstats.go
+++ b/util/topsql/stmtstats/stmtstats.go
@@ -78,6 +78,7 @@ func (s *StatementStats) OnExecutionFinished(sqlDigest, planDigest []byte, execD
 	item := s.GetOrCreateStatementStatsItem(sqlDigest, planDigest)
 
 	item.SumDurationNs += uint64(ns)
+	item.DurationCount++
 	// Count more data here.
 }
 
@@ -175,6 +176,10 @@ type StatementStatsItem struct {
 	// SumDurationNs is the total number of durations in nanoseconds.
 	SumDurationNs uint64
 
+	// DurationCount represents the number of SQL executions specially
+	// used to calculate SQLDuration.
+	DurationCount uint64
+
 	// KvStatsItem contains all indicators of kv layer.
 	KvStatsItem KvStatementStatsItem
 }
@@ -199,6 +204,7 @@ func (i *StatementStatsItem) Merge(other *StatementStatsItem) {
 	}
 	i.ExecCount += other.ExecCount
 	i.SumDurationNs += other.SumDurationNs
+	i.DurationCount += other.DurationCount
 	i.KvStatsItem.Merge(other.KvStatsItem)
 }
 


Test patch:
diff --git a/server/tidb_test.go b/server/tidb_test.go
index e739f332eb451..6b3e2661773b6 100644
--- a/server/tidb_test.go
+++ b/server/tidb_test.go
@@ -1757,6 +1757,7 @@ func TestTopSQLStatementStats(t *testing.T) {
 		if sqlStr, ok := sqlDigests[digest.SQLDigest]; ok {
 			found++
 			require.Equal(t, uint64(ExecCountPerSQL), item.ExecCount, sqlStr)
+			require.Equal(t, uint64(ExecCountPerSQL), item.DurationCount, sqlStr)
 			require.True(t, item.SumDurationNs > uint64(time.Millisecond*100*ExecCountPerSQL), sqlStr)
 			require.True(t, item.SumDurationNs < uint64(time.Millisecond*150*ExecCountPerSQL), sqlStr)
 			if strings.HasPrefix(sqlStr, "set global") {
diff --git a/util/topsql/reporter/datamodel_test.go b/util/topsql/reporter/datamodel_test.go
index bb9015c75bfa6..ba8d5ae85b78e 100644
--- a/util/topsql/reporter/datamodel_test.go
+++ b/util/topsql/reporter/datamodel_test.go
@@ -33,6 +33,7 @@ func Test_tsItem_toProto(t *testing.T) {
 		stmtStats: stmtstats.StatementStatsItem{
 			ExecCount:     3,
 			SumDurationNs: 50000,
+			DurationCount: 2,
 			KvStatsItem:   stmtstats.KvStatementStatsItem{KvExecCount: map[string]uint64{"": 4}},
 		},
 	}
@@ -41,6 +42,7 @@ func Test_tsItem_toProto(t *testing.T) {
 	assert.Equal(t, uint32(2), pb.CpuTimeMs)
 	assert.Equal(t, uint64(3), pb.StmtExecCount)
 	assert.Equal(t, uint64(50000), pb.StmtDurationSumNs)
+	assert.Equal(t, uint64(2), pb.StmtDurationCount)
 	assert.Equal(t, uint64(4), pb.StmtKvExecCount[""])
 }