From f06fb5acfbf8e934965ea6083b432e0f7aecfd01 Mon Sep 17 00:00:00 2001 From: HuaiyuXu <391585975@qq.com> Date: Wed, 30 Nov 2022 19:28:01 +0800 Subject: [PATCH] util, executor: refine the memory usage of delete multiple tables (#39489) close pingcap/tidb#35886 --- executor/delete.go | 17 ++++++++++++----- util/chunk/row.go | 20 +++++++++++++++----- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/executor/delete.go b/executor/delete.go index 9e64a47669f9f..3aa0932a07c22 100644 --- a/executor/delete.go +++ b/executor/delete.go @@ -175,8 +175,14 @@ func (e *DeleteExec) composeTblRowMap(tblRowMap tableRowMapType, colPosInfos []p return err } // tblRowMap[info.TblID][handle] hold the row datas binding to this table and this handle. - _, exist := tblRowMap[info.TblID].Get(handle) - memDelta := tblRowMap[info.TblID].Set(handle, joinedRow[info.Start:info.End]) + row, exist := tblRowMap[info.TblID].Get(handle) + if !exist { + row = make([]types.Datum, info.End-info.Start) + } + for i, d := range joinedRow[info.Start:info.End] { + d.Copy(&row[i]) + } + memDelta := tblRowMap[info.TblID].Set(handle, row) if !exist { memDelta += types.EstimatedMemUsage(joinedRow, 1) memDelta += int64(handle.ExtraMemSize()) @@ -192,6 +198,7 @@ func (e *DeleteExec) deleteMultiTablesByChunk(ctx context.Context) error { fields := retTypes(e.children[0]) chk := tryNewCacheChunk(e.children[0]) memUsageOfChk := int64(0) + joinedDatumRowBuffer := make([]types.Datum, len(fields)) for { e.memTracker.Consume(-memUsageOfChk) iter := chunk.NewIterator4Chunk(chk) @@ -206,13 +213,13 @@ func (e *DeleteExec) deleteMultiTablesByChunk(ctx context.Context) error { e.memTracker.Consume(memUsageOfChk) for joinedChunkRow := iter.Begin(); joinedChunkRow != iter.End(); joinedChunkRow = iter.Next() { - joinedDatumRow := joinedChunkRow.GetDatumRow(fields) - err := e.composeTblRowMap(tblRowMap, colPosInfos, joinedDatumRow) + joinedDatumRowBuffer = joinedChunkRow.GetDatumRowWithBuffer(fields, joinedDatumRowBuffer) + err := e.composeTblRowMap(tblRowMap, colPosInfos, joinedDatumRowBuffer) if err != nil { return err } } - chk = chunk.Renew(chk, e.maxChunkSize) + chk = tryNewCacheChunk(e.children[0]) } return e.removeRowsInTblRowMap(tblRowMap) diff --git a/util/chunk/row.go b/util/chunk/row.go index 96aa92acb65fb..04aba8f768bdd 100644 --- a/util/chunk/row.go +++ b/util/chunk/row.go @@ -115,10 +115,14 @@ func (r Row) GetJSON(colIdx int) types.BinaryJSON { // Keep in mind that GetDatumRow has a reference to r.c, which is a chunk, // this function works only if the underlying chunk is valid or unchanged. func (r Row) GetDatumRow(fields []*types.FieldType) []types.Datum { - datumRow := make([]types.Datum, 0, r.c.NumCols()) - for colIdx := 0; colIdx < r.c.NumCols(); colIdx++ { - datum := r.GetDatum(colIdx, fields[colIdx]) - datumRow = append(datumRow, datum) + datumRow := make([]types.Datum, r.c.NumCols()) + return r.GetDatumRowWithBuffer(fields, datumRow) +} + +// GetDatumRowWithBuffer gets datum using the buffer datumRow. +func (r Row) GetDatumRowWithBuffer(fields []*types.FieldType, datumRow []types.Datum) []types.Datum { + for colIdx := 0; colIdx < len(datumRow); colIdx++ { + r.GetDatumWithBuffer(colIdx, fields[colIdx], &datumRow[colIdx]) } return datumRow } @@ -126,6 +130,12 @@ func (r Row) GetDatumRow(fields []*types.FieldType) []types.Datum { // GetDatum implements the chunk.Row interface. func (r Row) GetDatum(colIdx int, tp *types.FieldType) types.Datum { var d types.Datum + r.GetDatumWithBuffer(colIdx, tp, &d) + return d +} + +// GetDatumWithBuffer gets datum using the buffer d. +func (r Row) GetDatumWithBuffer(colIdx int, tp *types.FieldType, d *types.Datum) types.Datum { switch tp.GetType() { case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: if !r.IsNull(colIdx) { @@ -192,7 +202,7 @@ func (r Row) GetDatum(colIdx int, tp *types.FieldType) types.Datum { d.SetMysqlJSON(r.GetJSON(colIdx)) } } - return d + return *d } // GetRaw returns the underlying raw bytes with the colIdx.