-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
inforschema, executor, util/kvcache, util/statement_summary : Add STATEMENTS_SUMMARY_EVICTED into information_schema #24513
Changes from 20 commits
1a96cbb
0c8920a
25ae806
529e346
38fa019
d78ca46
1cddd8f
33d865f
2d75e37
05703d8
eaf1caa
0163613
0935f75
c0227b6
0a168fe
b447b86
8e8792b
2a8ed11
12b6a87
373d344
0f24624
e2a18b1
6b7da7e
ebad974
3fcd196
073ff06
32e8df9
1092e72
7e8a8d8
252b43a
015b145
e061027
d3bf818
f59155b
efcad35
80167a3
dbc94c7
756c53e
43a4adc
be4b4e4
c6ce248
a8be817
fdec81a
01a92a4
9c503e5
b2278b2
d3ea973
a3ed839
9b243a5
eaffa1c
413ed0d
c91e5e3
0bd1f5e
f282833
16c83f9
cca919b
52cb27b
a31059d
4c9e65f
b7a87e1
5725827
b0776f5
b50b213
3b9fa88
cafa16a
f880324
f740b34
6c69920
caab2da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,319 @@ | ||||||||||||
package stmtsummary | ||||||||||||
djshow832 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
||||||||||||
import ( | ||||||||||||
"container/list" | ||||||||||||
"time" | ||||||||||||
|
||||||||||||
"github.com/pingcap/parser/mysql" | ||||||||||||
"github.com/pingcap/tidb/types" | ||||||||||||
) | ||||||||||||
|
||||||||||||
// stmtSummaryByDigestEvicted contents digests evicted from stmtSummaryByDigestMap | ||||||||||||
type stmtSummaryByDigestEvicted struct { | ||||||||||||
// record evicted data in intervals | ||||||||||||
// latest history data is Back() | ||||||||||||
history *list.List | ||||||||||||
} | ||||||||||||
|
||||||||||||
// element being stored in stmtSummaryByDigestEvicted | ||||||||||||
type stmtSummaryByDigestEvictedElement struct { | ||||||||||||
// *Kinds* of digest being evicted | ||||||||||||
digestKeyMap map[string]struct{} | ||||||||||||
|
||||||||||||
// summary of digest being evicted | ||||||||||||
sum *stmtSummaryByDigestElement | ||||||||||||
} | ||||||||||||
|
||||||||||||
// spawn a new pointer to stmtSummaryByDigestEvicted | ||||||||||||
func newStmtSummaryByDigestEvicted() *stmtSummaryByDigestEvicted { | ||||||||||||
return &stmtSummaryByDigestEvicted{ | ||||||||||||
history: list.New(), | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
// spawn a new pointer to stmtSummaryByDigestEvictedElement | ||||||||||||
func newStmtSummaryByDigestEvictedElement(beginTimeForCurrentInterval int64, intervalSeconds int64) *stmtSummaryByDigestEvictedElement { | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why use |
||||||||||||
ssElement := new(stmtSummaryByDigestElement) | ||||||||||||
ssElement.beginTime = beginTimeForCurrentInterval | ||||||||||||
ssElement.endTime = beginTimeForCurrentInterval + intervalSeconds | ||||||||||||
return &stmtSummaryByDigestEvictedElement{ | ||||||||||||
digestKeyMap: make(map[string]struct{}), | ||||||||||||
sum: ssElement, | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
// AddEvicted is used add an evicted record to stmtSummaryByDigestEvicted | ||||||||||||
func (ssbde *stmtSummaryByDigestEvicted) AddEvicted(evictedKey *stmtSummaryByDigestKey, evictedValue *stmtSummaryByDigest, historySize int) { | ||||||||||||
crazycs520 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
||||||||||||
// *need to get optimized*!! | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove the blank line and refine the comment. Need to optimize for what? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. currently, I simply check through all elements in evicted digest and history list. Assume the length of evicted digest is 'm', length of history list is 'n'. then time consumed on this operation is O(mn). This can be improved to O(m+n). |
||||||||||||
evictedValue.Lock() | ||||||||||||
defer evictedValue.Unlock() | ||||||||||||
for e := evictedValue.history.Back(); e != nil; e = e.Prev() { | ||||||||||||
eBeginTime := e.Value.(*stmtSummaryByDigestElement).beginTime | ||||||||||||
eEndTime := e.Value.(*stmtSummaryByDigestElement).endTime | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
|
||||||||||||
// prevent exceeding history size | ||||||||||||
for ssbde.history.Len() >= historySize && ssbde.history.Len() > 1 { | ||||||||||||
ssbde.history.Remove(ssbde.history.Front()) | ||||||||||||
} | ||||||||||||
|
||||||||||||
// look for match history interval | ||||||||||||
// no record in history | ||||||||||||
if ssbde.history.Len() == 0 && historySize > 0 { | ||||||||||||
beginTime := eBeginTime | ||||||||||||
intervalSeconds := eEndTime - eBeginTime | ||||||||||||
record := newStmtSummaryByDigestEvictedElement(beginTime, intervalSeconds) | ||||||||||||
record.addEvicted(evictedKey, e.Value.(*stmtSummaryByDigestElement)) | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
||||||||||||
ssbde.history.PushBack(record) | ||||||||||||
continue | ||||||||||||
} | ||||||||||||
|
||||||||||||
for h := ssbde.history.Back(); h != nil; h = h.Prev() { | ||||||||||||
sBeginTime := h.Value.(*stmtSummaryByDigestEvictedElement).sum.beginTime | ||||||||||||
sEndTime := h.Value.(*stmtSummaryByDigestEvictedElement).sum.endTime | ||||||||||||
|
||||||||||||
if sBeginTime <= eBeginTime && | ||||||||||||
sEndTime >= eEndTime { | ||||||||||||
// is in this history interval | ||||||||||||
h.Value.(*stmtSummaryByDigestEvictedElement).addEvicted(evictedKey, e.Value.(*stmtSummaryByDigestElement)) | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto. |
||||||||||||
break | ||||||||||||
} | ||||||||||||
|
||||||||||||
if sEndTime <= eBeginTime { | ||||||||||||
// digest is young, insert into new interval after this history interval | ||||||||||||
beginTime := eBeginTime | ||||||||||||
intervalSeconds := eEndTime - eBeginTime | ||||||||||||
record := newStmtSummaryByDigestEvictedElement(beginTime, intervalSeconds) | ||||||||||||
record.addEvicted(evictedKey, e.Value.(*stmtSummaryByDigestElement)) | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto. |
||||||||||||
ssbde.history.InsertAfter(record, h) | ||||||||||||
break | ||||||||||||
} | ||||||||||||
|
||||||||||||
if sBeginTime > eEndTime { | ||||||||||||
// digestElement is old | ||||||||||||
if h != ssbde.history.Front() { | ||||||||||||
// check older history digestEvictedElement | ||||||||||||
continue | ||||||||||||
} else if ssbde.history.Len() >= historySize { | ||||||||||||
// out of history size, abandon | ||||||||||||
break | ||||||||||||
} else { | ||||||||||||
// is oldest digest | ||||||||||||
// creat a digestEvictedElement and PushFront! | ||||||||||||
beginTime := eBeginTime | ||||||||||||
intervalSeconds := eEndTime - eBeginTime | ||||||||||||
record := newStmtSummaryByDigestEvictedElement(beginTime, intervalSeconds) | ||||||||||||
record.addEvicted(evictedKey, e.Value.(*stmtSummaryByDigestElement)) | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto. |
||||||||||||
ssbde.history.PushFront(record) | ||||||||||||
break | ||||||||||||
} | ||||||||||||
} | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does any test cover this? Because I think this situation should never happen. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. currently no. |
||||||||||||
} | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
// Clear up all records in stmtSummaryByDigestEvicted | ||||||||||||
func (ssbde *stmtSummaryByDigestEvicted) Clear() { | ||||||||||||
ssbde.history.Init() | ||||||||||||
} | ||||||||||||
|
||||||||||||
// add an evicted record to stmtSummaryByDigestEvictedElement | ||||||||||||
func (seElement *stmtSummaryByDigestEvictedElement) addEvicted(digestKey *stmtSummaryByDigestKey, digestValue *stmtSummaryByDigestElement) { | ||||||||||||
if digestKey != nil { | ||||||||||||
seElement.digestKeyMap[string(digestKey.Hash())] = struct{}{} | ||||||||||||
} | ||||||||||||
sumEvicted(seElement.sum, digestValue) | ||||||||||||
} | ||||||||||||
|
||||||||||||
// ToCurrentOtherDatum converts current evicted record to `other` record's datum | ||||||||||||
func (ssbde *stmtSummaryByDigestEvicted) ToCurrentOtherDatum() []types.Datum { | ||||||||||||
induceSsbd := new(stmtSummaryByDigest) | ||||||||||||
induceSsbd.stmtType = "" | ||||||||||||
induceSsbd.schemaName = "" | ||||||||||||
induceSsbd.digest = "" | ||||||||||||
induceSsbd.normalizedSQL = "" | ||||||||||||
induceSsbd.planDigest = "" | ||||||||||||
return ssbde.history.Back().Value.(*stmtSummaryByDigestEvictedElement).toOtherDatum(induceSsbd) | ||||||||||||
} | ||||||||||||
|
||||||||||||
// ToHistoryOtherDatum converts history evicted record to `other` record's datum | ||||||||||||
func (ssbde *stmtSummaryByDigestEvicted) ToHistoryOtherDatum() [][]types.Datum { | ||||||||||||
induceSsbd := new(stmtSummaryByDigest) | ||||||||||||
|
||||||||||||
var records [][]types.Datum | ||||||||||||
for e := ssbde.history.Front(); e != nil; e = e.Next() { | ||||||||||||
if record := e.Value.(*stmtSummaryByDigestEvictedElement).toOtherDatum(induceSsbd); record != nil { | ||||||||||||
records = append(records, record) | ||||||||||||
} | ||||||||||||
} | ||||||||||||
return records | ||||||||||||
} | ||||||||||||
|
||||||||||||
// ToEvictedCountDatum converts history evicted record to `evicted count` record's datum | ||||||||||||
func (ssbde *stmtSummaryByDigestEvicted) ToEvictedCountDatum() [][]types.Datum { | ||||||||||||
records := make([][]types.Datum, 0, ssbde.history.Len()) | ||||||||||||
for e := ssbde.history.Front(); e != nil; e = e.Next() { | ||||||||||||
if record := e.Value.(*stmtSummaryByDigestEvictedElement).toEvictedCountDatum(); record != nil { | ||||||||||||
records = append(records, record) | ||||||||||||
} | ||||||||||||
} | ||||||||||||
return records | ||||||||||||
} | ||||||||||||
|
||||||||||||
// toOtherDatum converts evicted record to `other` record's datum | ||||||||||||
func (seElement *stmtSummaryByDigestEvictedElement) toOtherDatum(ssbd *stmtSummaryByDigest) []types.Datum { | ||||||||||||
return seElement.sum.toDatum(ssbd) | ||||||||||||
} | ||||||||||||
|
||||||||||||
// toEvictedCountDatum converts evicted record to `EvictedCount` record's datum | ||||||||||||
func (seElement *stmtSummaryByDigestEvictedElement) toEvictedCountDatum() []types.Datum { | ||||||||||||
datum := types.MakeDatums( | ||||||||||||
types.NewTime(types.FromGoTime(time.Unix(seElement.sum.beginTime, 0)), mysql.TypeTimestamp, 0), | ||||||||||||
types.NewTime(types.FromGoTime(time.Unix(seElement.sum.endTime, 0)), mysql.TypeTimestamp, 0), | ||||||||||||
int64(len(seElement.digestKeyMap)), | ||||||||||||
) | ||||||||||||
return datum | ||||||||||||
} | ||||||||||||
|
||||||||||||
func (ssMap *stmtSummaryByDigestMap) ToEvictedCountDatum() [][]types.Datum { | ||||||||||||
return ssMap.other.ToEvictedCountDatum() | ||||||||||||
} | ||||||||||||
|
||||||||||||
// sumEvicted sum addWith into addTo | ||||||||||||
func sumEvicted(sumTo *stmtSummaryByDigestElement, addWith *stmtSummaryByDigestElement) { | ||||||||||||
// Time duration relation: addWith ⊆ sumTo | ||||||||||||
if sumTo.beginTime < addWith.beginTime { | ||||||||||||
sumTo.beginTime = addWith.beginTime | ||||||||||||
} | ||||||||||||
if sumTo.endTime > addWith.beginTime { | ||||||||||||
sumTo.endTime = addWith.endTime | ||||||||||||
} | ||||||||||||
// basic | ||||||||||||
sumTo.execCount += addWith.execCount | ||||||||||||
sumTo.sumErrors += addWith.sumErrors | ||||||||||||
sumTo.sumWarnings += addWith.sumWarnings | ||||||||||||
// latency | ||||||||||||
sumTo.sumLatency += addWith.sumLatency | ||||||||||||
sumTo.sumParseLatency += addWith.sumParseLatency | ||||||||||||
sumTo.sumCompileLatency += addWith.sumCompileLatency | ||||||||||||
if sumTo.maxLatency < addWith.maxLatency { | ||||||||||||
sumTo.maxLatency = addWith.maxLatency | ||||||||||||
} | ||||||||||||
if sumTo.maxCompileLatency < addWith.maxCompileLatency { | ||||||||||||
sumTo.maxCompileLatency = addWith.maxCompileLatency | ||||||||||||
} | ||||||||||||
if sumTo.minLatency > addWith.minLatency { | ||||||||||||
sumTo.minLatency = addWith.minLatency | ||||||||||||
} | ||||||||||||
// coprocessor | ||||||||||||
sumTo.sumNumCopTasks += addWith.sumNumCopTasks | ||||||||||||
if sumTo.maxCopProcessTime < addWith.maxCopProcessTime { | ||||||||||||
sumTo.maxCopProcessTime = addWith.maxCopProcessTime | ||||||||||||
} | ||||||||||||
if sumTo.maxCopWaitTime < addWith.maxCopWaitTime { | ||||||||||||
sumTo.maxCopWaitTime = addWith.maxCopWaitTime | ||||||||||||
} | ||||||||||||
// TiKV | ||||||||||||
sumTo.sumProcessTime += addWith.sumProcessTime | ||||||||||||
sumTo.sumWaitTime += addWith.sumWaitTime | ||||||||||||
sumTo.sumBackoffTime += addWith.sumBackoffTime | ||||||||||||
sumTo.sumTotalKeys += addWith.sumTotalKeys | ||||||||||||
sumTo.sumProcessedKeys += addWith.sumProcessedKeys | ||||||||||||
sumTo.sumRocksdbDeleteSkippedCount += addWith.sumRocksdbDeleteSkippedCount | ||||||||||||
sumTo.sumRocksdbKeySkippedCount += addWith.sumRocksdbKeySkippedCount | ||||||||||||
sumTo.sumRocksdbBlockCacheHitCount += addWith.sumRocksdbBlockCacheHitCount | ||||||||||||
sumTo.sumRocksdbBlockReadCount += addWith.sumRocksdbBlockReadCount | ||||||||||||
sumTo.sumRocksdbBlockReadByte += addWith.sumRocksdbBlockReadByte | ||||||||||||
if sumTo.maxProcessTime < addWith.maxProcessTime { | ||||||||||||
sumTo.maxProcessTime = addWith.maxProcessTime | ||||||||||||
} | ||||||||||||
if sumTo.maxWaitTime < addWith.maxWaitTime { | ||||||||||||
sumTo.maxWaitTime = addWith.maxWaitTime | ||||||||||||
} | ||||||||||||
if sumTo.maxBackoffTime < addWith.maxBackoffTime { | ||||||||||||
sumTo.maxBackoffTime = addWith.maxBackoffTime | ||||||||||||
} | ||||||||||||
if sumTo.maxTotalKeys < addWith.maxTotalKeys { | ||||||||||||
sumTo.maxTotalKeys = addWith.maxTotalKeys | ||||||||||||
} | ||||||||||||
if sumTo.maxProcessedKeys < addWith.maxProcessedKeys { | ||||||||||||
sumTo.maxProcessedKeys = addWith.maxProcessedKeys | ||||||||||||
} | ||||||||||||
if sumTo.maxRocksdbBlockReadByte < addWith.maxRocksdbBlockReadByte { | ||||||||||||
sumTo.maxRocksdbBlockReadByte = addWith.maxRocksdbBlockReadByte | ||||||||||||
} | ||||||||||||
if sumTo.maxRocksdbBlockCacheHitCount < addWith.maxRocksdbBlockCacheHitCount { | ||||||||||||
sumTo.maxRocksdbBlockCacheHitCount = addWith.maxRocksdbBlockCacheHitCount | ||||||||||||
} | ||||||||||||
if sumTo.maxRocksdbBlockReadCount < addWith.maxRocksdbBlockReadCount { | ||||||||||||
sumTo.maxRocksdbBlockReadCount = addWith.maxRocksdbBlockReadCount | ||||||||||||
} | ||||||||||||
if sumTo.maxRocksdbDeleteSkippedCount < addWith.maxRocksdbDeleteSkippedCount { | ||||||||||||
sumTo.maxRocksdbDeleteSkippedCount = addWith.maxRocksdbDeleteSkippedCount | ||||||||||||
} | ||||||||||||
if sumTo.maxRocksdbKeySkippedCount < addWith.maxRocksdbKeySkippedCount { | ||||||||||||
sumTo.maxRocksdbKeySkippedCount = addWith.maxRocksdbKeySkippedCount | ||||||||||||
} | ||||||||||||
// txn | ||||||||||||
sumTo.commitCount += addWith.commitCount | ||||||||||||
sumTo.sumGetCommitTsTime += addWith.sumGetCommitTsTime | ||||||||||||
sumTo.sumPrewriteTime += addWith.sumPrewriteTime | ||||||||||||
sumTo.sumCommitTime += addWith.sumCommitTime | ||||||||||||
sumTo.sumLocalLatchTime += addWith.sumLocalLatchTime | ||||||||||||
sumTo.sumCommitBackoffTime += addWith.sumCommitBackoffTime | ||||||||||||
sumTo.sumResolveLockTime += addWith.sumResolveLockTime | ||||||||||||
sumTo.sumWriteKeys += addWith.sumWriteKeys | ||||||||||||
sumTo.sumWriteSize += addWith.sumWriteSize | ||||||||||||
sumTo.sumPrewriteRegionNum += addWith.sumPrewriteRegionNum | ||||||||||||
sumTo.sumTxnRetry += addWith.sumTxnRetry | ||||||||||||
sumTo.sumBackoffTimes += sumTo.sumBackoffTimes | ||||||||||||
if sumTo.maxGetCommitTsTime < addWith.maxGetCommitTsTime { | ||||||||||||
sumTo.maxGetCommitTsTime = addWith.maxGetCommitTsTime | ||||||||||||
} | ||||||||||||
if sumTo.maxPrewriteTime < addWith.maxPrewriteTime { | ||||||||||||
sumTo.maxPrewriteTime = addWith.maxPrewriteTime | ||||||||||||
} | ||||||||||||
if sumTo.maxCommitTime < addWith.maxCommitTime { | ||||||||||||
sumTo.maxCommitTime = addWith.maxCommitTime | ||||||||||||
} | ||||||||||||
if sumTo.maxLocalLatchTime < addWith.maxLocalLatchTime { | ||||||||||||
sumTo.maxLocalLatchTime = addWith.maxLocalLatchTime | ||||||||||||
} | ||||||||||||
if sumTo.maxCommitBackoffTime < addWith.maxCommitBackoffTime { | ||||||||||||
sumTo.maxCommitBackoffTime = addWith.maxCommitBackoffTime | ||||||||||||
} | ||||||||||||
if sumTo.maxResolveLockTime < addWith.maxResolveLockTime { | ||||||||||||
sumTo.maxResolveLockTime = addWith.maxResolveLockTime | ||||||||||||
} | ||||||||||||
if sumTo.maxWriteKeys < addWith.maxWriteKeys { | ||||||||||||
sumTo.maxWriteKeys = addWith.maxWriteKeys | ||||||||||||
} | ||||||||||||
if sumTo.maxWriteSize < addWith.maxWriteSize { | ||||||||||||
sumTo.maxWriteSize = addWith.maxWriteSize | ||||||||||||
} | ||||||||||||
if sumTo.maxPrewriteRegionNum < sumTo.maxPrewriteRegionNum { | ||||||||||||
sumTo.maxPrewriteRegionNum = addWith.maxPrewriteRegionNum | ||||||||||||
} | ||||||||||||
if sumTo.maxTxnRetry < addWith.maxTxnRetry { | ||||||||||||
sumTo.maxTxnRetry = addWith.maxTxnRetry | ||||||||||||
} | ||||||||||||
// other | ||||||||||||
sumTo.sumMem += addWith.sumMem | ||||||||||||
sumTo.sumDisk += addWith.sumDisk | ||||||||||||
sumTo.sumAffectedRows += addWith.sumAffectedRows | ||||||||||||
sumTo.sumKVTotal += addWith.sumKVTotal | ||||||||||||
sumTo.sumPDTotal += addWith.sumPDTotal | ||||||||||||
sumTo.sumBackoffTotal += addWith.sumBackoffTotal | ||||||||||||
sumTo.sumWriteSQLRespTotal += addWith.sumWriteSQLRespTotal | ||||||||||||
if sumTo.maxMem < addWith.maxMem { | ||||||||||||
sumTo.maxMem = addWith.maxMem | ||||||||||||
} | ||||||||||||
if sumTo.maxDisk < addWith.maxDisk { | ||||||||||||
sumTo.maxDisk = addWith.maxDisk | ||||||||||||
} | ||||||||||||
// plan cache | ||||||||||||
sumTo.planCacheHits += addWith.planCacheHits | ||||||||||||
// pessimistic execution retry information | ||||||||||||
sumTo.execRetryCount += addWith.execRetryCount | ||||||||||||
sumTo.execRetryTime += addWith.execRetryTime | ||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Look like this function is useless? just use
e.rows = stmtsummary.StmtSummaryByDigestMap.ToEvictedCountDatum()
in line#153?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, I wasn't aware of it.