Skip to content

Commit

Permalink
*: improve plan cache param eval and insert const (#10746)
Browse files Browse the repository at this point in the history
  • Loading branch information
lysu authored and jackysp committed Aug 27, 2019
1 parent b438bf2 commit 4cd5d15
Show file tree
Hide file tree
Showing 19 changed files with 366 additions and 93 deletions.
28 changes: 15 additions & 13 deletions executor/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -677,15 +677,16 @@ func (b *executorBuilder) buildInsert(v *plannercore.Insert) Executor {
baseExec.initCap = chunk.ZeroCapacity

ivs := &InsertValues{
baseExecutor: baseExec,
Table: v.Table,
Columns: v.Columns,
Lists: v.Lists,
SetList: v.SetList,
GenColumns: v.GenCols.Columns,
GenExprs: v.GenCols.Exprs,
hasRefCols: v.NeedFillDefaultValue,
SelectExec: selectExec,
baseExecutor: baseExec,
Table: v.Table,
Columns: v.Columns,
Lists: v.Lists,
SetList: v.SetList,
GenColumns: v.GenCols.Columns,
GenExprs: v.GenCols.Exprs,
allAssignmentsAreConstant: v.AllAssignmentsAreConstant,
hasRefCols: v.NeedFillDefaultValue,
SelectExec: selectExec,
}
err := ivs.initInsertColumns()
if err != nil {
Expand Down Expand Up @@ -1399,10 +1400,11 @@ func (b *executorBuilder) buildUpdate(v *plannercore.Update) Executor {
base := newBaseExecutor(b.ctx, v.Schema(), v.ExplainID(), selExec)
base.initCap = chunk.ZeroCapacity
updateExec := &UpdateExec{
baseExecutor: base,
OrderedList: v.OrderedList,
tblID2table: tblID2table,
tblColPosInfos: v.TblColPosInfos,
baseExecutor: base,
OrderedList: v.OrderedList,
allAssignmentsAreConstant: v.AllAssignmentsAreConstant,
tblID2table: tblID2table,
tblColPosInfos: v.TblColPosInfos,
}
return updateExec
}
Expand Down
4 changes: 3 additions & 1 deletion executor/insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,9 @@ func (e *InsertExec) Open(ctx context.Context) error {
if e.SelectExec != nil {
return e.SelectExec.Open(ctx)
}
e.initEvalBuffer()
if !e.allAssignmentsAreConstant {
e.initEvalBuffer()
}
return nil
}

Expand Down
35 changes: 34 additions & 1 deletion executor/insert_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ type InsertValues struct {

insertColumns []*table.Column

allAssignmentsAreConstant bool

// colDefaultVals is used to store casted default value.
// Because not every insert statement needs colDefaultVals, so we will init the buffer lazily.
colDefaultVals []defaultVal
Expand Down Expand Up @@ -199,10 +201,16 @@ func insertRows(ctx context.Context, base insertCommon) (err error) {
batchInsert := sessVars.BatchInsert && !sessVars.InTxn()
batchSize := sessVars.DMLBatchSize

evalRowFunc := e.fastEvalRow
if !e.allAssignmentsAreConstant {
evalRowFunc = e.evalRow
}

rows := make([][]types.Datum, 0, len(e.Lists))
for i, list := range e.Lists {
e.rowCount++
row, err := e.evalRow(ctx, list, i)
var row []types.Datum
row, err = evalRowFunc(ctx, list, i)
if err != nil {
return err
}
Expand Down Expand Up @@ -278,6 +286,31 @@ func (e *InsertValues) evalRow(ctx context.Context, list []expression.Expression
return e.fillRow(ctx, row, hasValue)
}

var emptyRow chunk.Row

func (e *InsertValues) fastEvalRow(ctx context.Context, list []expression.Expression, rowIdx int) ([]types.Datum, error) {
rowLen := len(e.Table.Cols())
if e.hasExtraHandle {
rowLen++
}
row := make([]types.Datum, rowLen)
hasValue := make([]bool, rowLen)
for i, expr := range list {
con := expr.(*expression.Constant)
val, err := con.Eval(emptyRow)
if err = e.handleErr(e.insertColumns[i], &val, rowIdx, err); err != nil {
return nil, err
}
val1, err := table.CastValue(e.ctx, val, e.insertColumns[i].ToInfo())
if err = e.handleErr(e.insertColumns[i], &val, rowIdx, err); err != nil {
return nil, err
}
offset := e.insertColumns[i].Offset
row[offset], hasValue[offset] = val1, true
}
return e.fillRow(ctx, row, hasValue)
}

// setValueForRefColumn set some default values for the row to eval the row value with other columns,
// it follows these rules:
// 1. for nullable and no default value column, use NULL.
Expand Down
44 changes: 39 additions & 5 deletions executor/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ type UpdateExec struct {
matched uint64 // a counter of matched rows during update
// tblColPosInfos stores relationship between column ordinal to its table handle.
// the columns ordinals is present in ordinal range format, @see plannercore.TblColPosInfos
tblColPosInfos plannercore.TblColPosInfoSlice
evalBuffer chunk.MutRow
tblColPosInfos plannercore.TblColPosInfoSlice
evalBuffer chunk.MutRow
allAssignmentsAreConstant bool
}

func (e *UpdateExec) exec(ctx context.Context, schema *expression.Schema) ([]types.Datum, error) {
Expand Down Expand Up @@ -165,7 +166,13 @@ func (e *UpdateExec) fetchChunkRows(ctx context.Context) error {
}
globalRowIdx := 0
chk := newFirstChunk(e.children[0])
e.evalBuffer = chunk.MutRowFromTypes(fields)
if !e.allAssignmentsAreConstant {
e.evalBuffer = chunk.MutRowFromTypes(fields)
}
composeFunc := e.fastComposeNewRow
if !e.allAssignmentsAreConstant {
composeFunc = e.composeNewRow
}
for {
err := Next(ctx, e.children[0], chk)
if err != nil {
Expand All @@ -175,11 +182,10 @@ func (e *UpdateExec) fetchChunkRows(ctx context.Context) error {
if chk.NumRows() == 0 {
break
}

for rowIdx := 0; rowIdx < chk.NumRows(); rowIdx++ {
chunkRow := chk.GetRow(rowIdx)
datumRow := chunkRow.GetDatumRow(fields)
newRow, err1 := e.composeNewRow(globalRowIdx, datumRow, colsInfo)
newRow, err1 := composeFunc(globalRowIdx, datumRow, colsInfo)
if err1 != nil {
return err1
}
Expand Down Expand Up @@ -208,6 +214,34 @@ func (e *UpdateExec) handleErr(colName model.CIStr, rowIdx int, err error) error
return err
}

func (e *UpdateExec) fastComposeNewRow(rowIdx int, oldRow []types.Datum, cols []*table.Column) ([]types.Datum, error) {
newRowData := types.CloneRow(oldRow)
for _, assign := range e.OrderedList {
handleIdx, handleFound := e.tblColPosInfos.FindHandle(assign.Col.Index)
if handleFound && e.canNotUpdate(oldRow[handleIdx]) {
continue
}

con := assign.Expr.(*expression.Constant)
val, err := con.Eval(emptyRow)
if err = e.handleErr(assign.Col.ColName, rowIdx, err); err != nil {
return nil, err
}

// info of `_tidb_rowid` column is nil.
// No need to cast `_tidb_rowid` column value.
if cols[assign.Col.Index] != nil {
val, err = table.CastValue(e.ctx, val, cols[assign.Col.Index].ColumnInfo)
if err = e.handleErr(assign.Col.ColName, rowIdx, err); err != nil {
return nil, err
}
}

newRowData[assign.Col.Index] = *val.Copy()
}
return newRowData, nil
}

func (e *UpdateExec) composeNewRow(rowIdx int, oldRow []types.Datum, cols []*table.Column) ([]types.Datum, error) {
newRowData := types.CloneRow(oldRow)
e.evalBuffer.SetDatums(newRowData...)
Expand Down
9 changes: 6 additions & 3 deletions expression/builtin_compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,7 @@ func tryToConvertConstantInt(ctx sessionctx.Context, targetFieldType *types.Fiel
Value: dt,
RetType: targetFieldType,
DeferredExpr: con.DeferredExpr,
ParamMarker: con.ParamMarker,
}, false
}

Expand Down Expand Up @@ -1140,6 +1141,7 @@ func RefineComparedConstant(ctx sessionctx.Context, targetFieldType types.FieldT
Value: intDatum,
RetType: &targetFieldType,
DeferredExpr: con.DeferredExpr,
ParamMarker: con.ParamMarker,
}, false
}
switch op {
Expand All @@ -1154,7 +1156,7 @@ func RefineComparedConstant(ctx sessionctx.Context, targetFieldType types.FieldT
return tryToConvertConstantInt(ctx, &targetFieldType, resultCon)
}
case opcode.NullEQ, opcode.EQ:
switch con.RetType.EvalType() {
switch con.GetType().EvalType() {
// An integer value equal or NULL-safe equal to a float value which contains
// non-zero decimal digits is definitely false.
// e.g.,
Expand All @@ -1181,6 +1183,7 @@ func RefineComparedConstant(ctx sessionctx.Context, targetFieldType types.FieldT
Value: intDatum,
RetType: &targetFieldType,
DeferredExpr: con.DeferredExpr,
ParamMarker: con.ParamMarker,
}, false
}
}
Expand All @@ -1201,7 +1204,7 @@ func (c *compareFunctionClass) refineArgs(ctx sessionctx.Context, args []Express
if arg0IsInt && !arg0IsCon && !arg1IsInt && arg1IsCon {
arg1, isExceptional = RefineComparedConstant(ctx, *arg0Type, arg1, c.op)
finalArg1 = arg1
if isExceptional && arg1.RetType.EvalType() == types.ETInt {
if isExceptional && arg1.GetType().EvalType() == types.ETInt {
// Judge it is inf or -inf
// For int:
// inf: 01111111 & 1 == 1
Expand All @@ -1220,7 +1223,7 @@ func (c *compareFunctionClass) refineArgs(ctx sessionctx.Context, args []Express
if arg1IsInt && !arg1IsCon && !arg0IsInt && arg0IsCon {
arg0, isExceptional = RefineComparedConstant(ctx, *arg1Type, arg0, symmetricOp[c.op])
finalArg0 = arg0
if isExceptional && arg0.RetType.EvalType() == types.ETInt {
if isExceptional && arg0.GetType().EvalType() == types.ETInt {
if arg0.Value.GetInt64()&1 == 1 {
isNegativeInfinite = true
} else {
Expand Down
Loading

0 comments on commit 4cd5d15

Please sign in to comment.