Skip to content
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

planner, executor: fix haven't track the memory usage of PointGet/BatchPointGet #21230

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f76abb3
fix statement-level optimize hint will be ignored when `tryFastPlan` …
zhaoxugang Nov 23, 2020
5c81c3f
fix import,test sql
zhaoxugang Nov 23, 2020
83f4248
fix error
zhaoxugang Nov 23, 2020
7f58a62
fix unit test
zhaoxugang Nov 23, 2020
e4aa904
fix unit test
zhaoxugang Nov 23, 2020
291e2c6
fix unit test
zhaoxugang Nov 23, 2020
c9f3966
fix unit test
zhaoxugang Nov 23, 2020
87d0476
fix test
zhaoxugang Dec 11, 2020
4ff8172
fix memory track
zhaoxugang Dec 13, 2020
6ada448
fix test,revert changes about memory hit
zhaoxugang Dec 13, 2020
b521483
Merge remote-tracking branch 'origin/master' into point-get-member-hint
zhaoxugang Dec 15, 2020
93f09b1
fix
zhaoxugang Dec 17, 2020
5883956
fix
zhaoxugang Dec 25, 2020
08d4671
fix
zhaoxugang Jan 3, 2021
8fd842c
fix
zhaoxugang Jan 4, 2021
86a523a
fix
zhaoxugang Jan 4, 2021
93c21bd
fix
zhaoxugang Jan 13, 2021
97579d9
Merge branch 'master' into point-get-member-hint
zhaoxugang Jan 16, 2021
facbc93
Merge branch 'master' into point-get-member-hint
zhaoxugang Jan 23, 2021
006ac37
Merge branch 'master' into point-get-member-hint
ti-srebot Feb 18, 2021
092914a
Merge branch 'master' into point-get-member-hint
zhaoxugang Feb 18, 2021
7a7e04a
Merge remote-tracking branch 'origin/point-get-member-hint' into poin…
zhaoxugang Feb 18, 2021
65feff2
Merge branch 'master' into point-get-member-hint
ti-chi-bot Feb 22, 2021
279e4c5
Merge branch 'master' into point-get-member-hint
zhaoxugang Feb 22, 2021
1430ee2
Merge remote-tracking branch 'origin/point-get-member-hint' into poin…
zhaoxugang Feb 22, 2021
ab74f22
Merge branch 'master' into point-get-member-hint
zhaoxugang Mar 7, 2021
f2ae417
Merge branch 'master' into point-get-member-hint
zhaoxugang Mar 28, 2021
a5fa934
Merge branch 'master-upstream' into point-get-member-hint
zhaoxugang Jan 30, 2022
7d2359a
Merge branch 'master-upstream' into point-get-member-hint
zhaoxugang Feb 11, 2022
46013d0
format fix
zhaoxugang Feb 11, 2022
47e7c0a
fix bug
zhaoxugang Feb 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions executor/batch_point_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/pingcap/tidb/util/codec"
"github.com/pingcap/tidb/util/hack"
"github.com/pingcap/tidb/util/math"
"github.com/pingcap/tidb/util/memory"
"github.com/pingcap/tidb/util/rowcodec"
)

Expand Down Expand Up @@ -68,6 +69,8 @@ type BatchPointGetExec struct {

snapshot kv.Snapshot
stats *runtimeStatsWithSnapshot

memTracker *memory.Tracker
}

// buildVirtualColumnInfo saves virtual column indices and sort them in definition order
Expand Down Expand Up @@ -123,11 +126,18 @@ func (e *BatchPointGetExec) Open(context.Context) error {
}
e.snapshot = snapshot
e.batchGetter = batchGetter

e.memTracker = memory.NewTracker(e.id, -1)
e.memTracker.AttachTo(e.ctx.GetSessionVars().StmtCtx.MemTracker)
return nil
}

// Close implements the Executor interface.
func (e *BatchPointGetExec) Close() error {

e.memTracker.Consume(-e.memTracker.BytesConsumed())
e.memTracker = nil

if e.runtimeStats != nil && e.snapshot != nil {
e.snapshot.DelOption(kv.CollectRuntimeStats)
}
Expand Down Expand Up @@ -192,6 +202,7 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error {
continue
}

e.memTracker.Consume(types.EstimatedMemUsage(idxVals, 1))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this line can be put at the beginning of the loop.

First, datumsContainNull(idxVals) will be true if ANY datum in idxVals is Null.
Second, a Null datum object still consuming memory.

physID := getPhysID(e.tblInfo, idxVals[e.partPos].GetInt64())
idxKey, err1 := EncodeUniqueIndexKey(e.ctx, e.tblInfo, e.idxInfo, idxVals, physID)
if err1 != nil && !kv.ErrNotExist.Equal(err1) {
Expand Down Expand Up @@ -321,6 +332,7 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error {
tID = getPhysID(e.tblInfo, d.GetInt64())
}
}
e.memTracker.Consume(int64(cap(handle.Encoded())))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IntHandle.Encoded() will cause more overhead.
I think maybe we need a kv.Handle.MemoryUsage() to deal with the different kinds of handles.

Besides, e.handles will change in following codes (see line no. 374 & 392). So it would be better to put this codes after line no. 374 handles = append(handles, e.handles[i]).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no kv.Handle.MemoryUsage()...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant maybe we can add such a method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

key := tablecodec.EncodeRowKeyWithHandle(tID, handle)
keys[i] = key
}
Expand Down Expand Up @@ -349,6 +361,8 @@ func (e *BatchPointGetExec) initialize(ctx context.Context) error {
e.values = make([][]byte, 0, len(values))
for i, key := range keys {
val := values[string(key)]
e.memTracker.Consume(int64(cap(val)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto, not all val will be append to e.values. I think it would be better to put after e.values = append(e.values, val).


if len(val) == 0 {
if e.idxInfo != nil && (!e.tblInfo.IsCommonHandle || !e.idxInfo.Primary) {
return kv.ErrNotExist.GenWithStack("inconsistent extra index %s, handle %d not found in table",
Expand Down
12 changes: 12 additions & 0 deletions executor/point_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/pingcap/tidb/util/chunk"
"github.com/pingcap/tidb/util/codec"
"github.com/pingcap/tidb/util/execdetails"
"github.com/pingcap/tidb/util/memory"
"github.com/pingcap/tidb/util/rowcodec"
)

Expand Down Expand Up @@ -81,6 +82,8 @@ type PointGetExecutor struct {
virtualColumnRetFieldTypes []*types.FieldType

stats *runtimeStatsWithSnapshot

memTracker *memory.Tracker
}

// Init set fields needed for PointGetExecutor reuse, this does NOT change baseExecutor field
Expand Down Expand Up @@ -140,11 +143,18 @@ func (e *PointGetExecutor) Open(context.Context) error {
e.snapshot.SetOption(kv.ReplicaRead, kv.ReplicaReadFollower)
}
e.snapshot.SetOption(kv.TaskID, e.ctx.GetSessionVars().StmtCtx.TaskID)

e.memTracker = memory.NewTracker(e.id, -1)
e.memTracker.AttachTo(e.ctx.GetSessionVars().StmtCtx.MemTracker)
return nil
}

// Close implements the Executor interface.
func (e *PointGetExecutor) Close() error {

e.memTracker.Consume(-e.memTracker.BytesConsumed())
e.memTracker = nil

if e.runtimeStats != nil && e.snapshot != nil {
e.snapshot.DelOption(kv.CollectRuntimeStats)
}
Expand Down Expand Up @@ -247,6 +257,8 @@ func (e *PointGetExecutor) Next(ctx context.Context, req *chunk.Chunk) error {
}
return nil
}
e.memTracker.Consume(int64(cap(val)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

val is just a local variable, and will be released after Next() returned.

I think we need tracking usage of executor's significant memory consuming members, such as idxKey, handleVal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zhaoxugang PTAL this comment. Rest LGTM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the point_get_exec mabe should't track memory,because the memory tracker should track the data from store but the data from store is return to client immediately.and the idxKey, handleVal is only one for point_get, it's Constant level so should't track.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we should not track memory at constant level ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right...I have done


err = DecodeRowValToChunk(e.base().ctx, e.schema, e.tblInfo, e.handle, val, req, e.rowDecoder)
if err != nil {
return err
Expand Down
26 changes: 26 additions & 0 deletions session/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3145,6 +3145,32 @@ func (s *testSessionSuite2) TestStmtHints(c *C) {
c.Assert(tk.Se.GetSessionVars().GetReplicaRead(), Equals, kv.ReplicaReadFollower)
}

// Test memory track in POINT_GET/BATCH_POINT_GET for issue 21653
func (s *testSessionSuite2) TestPointGetMemoryTracking(c *C) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Could you directly validate the tracked memory usage?
  2. Please also add tests for clustered index whose type is not an integer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't directly validate the memory usage,do you have some advices to do it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, what is the difference between integer and others, why need add tests for clustered index whose type is not an integer.

tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1(a int primary key);")
config.UpdateGlobal(func(conf *config.Config) {
conf.OOMAction = config.OOMActionCancel
})
tk.MustExec("insert into t1 values (1);")
tk.MustQuery("select * from t1 where a = 1;").Check(testkit.Rows("1"))
tk.MustExec("set tidb_mem_quota_query=1;")
err := tk.QueryToErr("select * from t1 where a = 1;")
wshwsh12 marked this conversation as resolved.
Show resolved Hide resolved
c.Assert(err, NotNil)
c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*")
err = tk.QueryToErr("select * from t1 where a in (1,2,3);")
c.Assert(err, NotNil)
c.Assert(err.Error(), Matches, "Out Of Memory Quota!.*")
tk.MustExec("set tidb_mem_quota_query=1024;")
tk.MustQuery("select * from t1 where a = 1;").Check(testkit.Rows("1"))
err = tk.QueryToErr("select * from t1 where a = 1;")
c.Check(err, IsNil)
err = tk.QueryToErr("select * from t1 where a in (1,2,3);")
c.Check(err, IsNil)
}

func (s *testSessionSuite3) TestPessimisticLockOnPartition(c *C) {
// This test checks that 'select ... for update' locks the partition instead of the table.
// Cover a bug that table ID is used to encode the lock key mistakenly.
Expand Down