From 598ccada4065e4871bc5bce53a039cbb598a6d82 Mon Sep 17 00:00:00 2001 From: Zhou Kunqin <25057648+time-and-fate@users.noreply.github.com> Date: Thu, 30 Nov 2023 21:14:48 +0800 Subject: [PATCH] *: code preparations for supporting build range for like function on new collation columns (#48972) ref pingcap/tidb#48181 --- pkg/executor/point_get.go | 6 +- pkg/planner/core/point_get_plan.go | 15 +- .../core/testdata/index_merge_suite_out.json | 4 +- pkg/util/ranger/detacher.go | 12 +- pkg/util/ranger/points.go | 56 +- pkg/util/ranger/ranger.go | 58 +- pkg/util/ranger/ranger_test.go | 4 +- pkg/util/ranger/types.go | 2 +- .../r/executor/point_get.result | 28 +- tests/integrationtest/r/explain_easy.result | 4 +- .../r/expression/charset_and_collation.result | 8 +- .../r/expression/issues.result | 2 +- .../rule/rule_derive_topn_from_window.result | 2 +- .../r/planner/core/indexmerge_path.result | 32 +- .../r/planner/core/range_scan_for_like.result | 999 ++++++++++++++++++ .../t/planner/core/range_scan_for_like.test | 243 +++++ 16 files changed, 1377 insertions(+), 98 deletions(-) create mode 100644 tests/integrationtest/r/planner/core/range_scan_for_like.result create mode 100644 tests/integrationtest/t/planner/core/range_scan_for_like.test diff --git a/pkg/executor/point_get.go b/pkg/executor/point_get.go index c7f20258874d3..42b1d8930c68b 100644 --- a/pkg/executor/point_get.go +++ b/pkg/executor/point_get.go @@ -540,11 +540,13 @@ func EncodeUniqueIndexValuesForKey(ctx sessionctx.Context, tblInfo *model.TableI colInfo := tblInfo.Columns[idxInfo.Columns[i].Offset] // table.CastValue will append 0x0 if the string value's length is smaller than the BINARY column's length. // So we don't use CastValue for string value for now. - // TODO: merge two if branch. + // TODO: The first if branch should have been removed, because the functionality of set the collation of the datum + // have been moved to util/ranger (normal path) and getNameValuePairs/getPointGetValue (fast path). But this change + // will be cherry-picked to a hotfix, so we choose to be a bit conservative and keep this for now. if colInfo.GetType() == mysql.TypeString || colInfo.GetType() == mysql.TypeVarString || colInfo.GetType() == mysql.TypeVarchar { var str string str, err = idxVals[i].ToString() - idxVals[i].SetString(str, colInfo.FieldType.GetCollate()) + idxVals[i].SetString(str, idxVals[i].Collation()) } else if colInfo.GetType() == mysql.TypeEnum && (idxVals[i].Kind() == types.KindString || idxVals[i].Kind() == types.KindBytes || idxVals[i].Kind() == types.KindBinaryLiteral) { var str string var e types.Enum diff --git a/pkg/planner/core/point_get_plan.go b/pkg/planner/core/point_get_plan.go index a4f501e308085..8d5406d2e706c 100644 --- a/pkg/planner/core/point_get_plan.go +++ b/pkg/planner/core/point_get_plan.go @@ -1438,7 +1438,15 @@ func getNameValuePairs(ctx sessionctx.Context, tbl *model.TableInfo, tblName mod col := model.FindColumnInfo(tbl.Cols(), colName.Name.Name.L) if col == nil { // Handling the case when the column is _tidb_rowid. return append(nvPairs, nameValuePair{colName: colName.Name.Name.L, colFieldType: types.NewFieldType(mysql.TypeLonglong), value: d, con: con}), false - } else if col.GetType() == mysql.TypeString && col.GetCollate() == charset.CollationBin { // This type we needn't to pad `\0` in here. + } + + // As in buildFromBinOp in util/ranger, when we build key from the expression to do range scan or point get on + // a string column, we should set the collation of the string datum to collation of the column. + if col.FieldType.EvalType() == types.ETString && (d.Kind() == types.KindString || d.Kind() == types.KindBinaryLiteral) { + d.SetString(d.GetString(), col.FieldType.GetCollate()) + } + + if col.GetType() == mysql.TypeString && col.GetCollate() == charset.CollationBin { // This type we needn't to pad `\0` in here. return append(nvPairs, nameValuePair{colName: colName.Name.Name.L, colFieldType: &col.FieldType, value: d, con: con}), false } if !checkCanConvertInPointGet(col, d) { @@ -1468,6 +1476,11 @@ func getPointGetValue(stmtCtx *stmtctx.StatementContext, col *model.ColumnInfo, if !checkCanConvertInPointGet(col, *d) { return nil } + // As in buildFromBinOp in util/ranger, when we build key from the expression to do range scan or point get on + // a string column, we should set the collation of the string datum to collation of the column. + if col.FieldType.EvalType() == types.ETString && (d.Kind() == types.KindString || d.Kind() == types.KindBinaryLiteral) { + d.SetString(d.GetString(), col.FieldType.GetCollate()) + } dVal, err := d.ConvertTo(stmtCtx.TypeCtx(), &col.FieldType) if err != nil { return nil diff --git a/pkg/planner/core/testdata/index_merge_suite_out.json b/pkg/planner/core/testdata/index_merge_suite_out.json index 3d67e5e372251..182dcd0ec61dd 100644 --- a/pkg/planner/core/testdata/index_merge_suite_out.json +++ b/pkg/planner/core/testdata/index_merge_suite_out.json @@ -174,8 +174,8 @@ "Plan": [ "Selection 1.42 root eq(test.t8.s5, \"test,2\")", "└─IndexMerge 0.59 root type: intersection", - " ├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t8, index:is2(s2) range:(0x616263,+inf], keep order:false, stats:pseudo", - " ├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t8, index:is3(s3) range:(0x636261,+inf], keep order:false, stats:pseudo", + " ├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t8, index:is2(s2) range:(\"abc\",+inf], keep order:false, stats:pseudo", + " ├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t8, index:is3(s3) range:(\"cba\",+inf], keep order:false, stats:pseudo", " ├─IndexRangeScan(Build) 20.00 cop[tikv] table:t8, index:is4(s4) range:[\"aA\",\"aA\"], [\"??\",\"??\"], keep order:false, stats:pseudo", " └─Selection(Probe) 0.59 cop[tikv] gt(test.t8.s3, \"cba\"), like(test.t8.s1, \"啊A%\", 92)", " └─TableRowIDScan 2.22 cop[tikv] table:t8 keep order:false, stats:pseudo" diff --git a/pkg/util/ranger/detacher.go b/pkg/util/ranger/detacher.go index cf218f32f9dfd..2aedcb0cea7ab 100644 --- a/pkg/util/ranger/detacher.go +++ b/pkg/util/ranger/detacher.go @@ -303,7 +303,7 @@ func unionColumnValues(lhs, rhs []*valueInfo) []*valueInfo { // detachCNFCondAndBuildRangeForIndex will detach the index filters from table filters. These conditions are connected with `and` // It will first find the point query column and then extract the range query column. // considerDNF is true means it will try to extract access conditions from the DNF expressions. -func (d *rangeDetacher) detachCNFCondAndBuildRangeForIndex(conditions []expression.Expression, tpSlice []*types.FieldType, considerDNF bool) (*DetachRangeResult, error) { +func (d *rangeDetacher) detachCNFCondAndBuildRangeForIndex(conditions []expression.Expression, newTpSlice []*types.FieldType, considerDNF bool) (*DetachRangeResult, error) { var ( eqCount int ranges Ranges @@ -316,7 +316,7 @@ func (d *rangeDetacher) detachCNFCondAndBuildRangeForIndex(conditions []expressi return res, nil } var remainedConds []expression.Expression - ranges, accessConds, remainedConds, err = d.buildRangeOnColsByCNFCond(tpSlice, len(accessConds), accessConds) + ranges, accessConds, remainedConds, err = d.buildRangeOnColsByCNFCond(newTpSlice, len(accessConds), accessConds) if err != nil { return nil, err } @@ -452,7 +452,7 @@ func (d *rangeDetacher) detachCNFCondAndBuildRangeForIndex(conditions []expressi } // `eqOrInCount` must be 0 when coming here. res.AccessConds, res.RemainedConds = detachColumnCNFConditions(d.sctx, newConditions, checker) - ranges, res.AccessConds, remainedConds, err = d.buildCNFIndexRange(tpSlice, 0, res.AccessConds) + ranges, res.AccessConds, remainedConds, err = d.buildCNFIndexRange(newTpSlice, 0, res.AccessConds) if err != nil { return nil, err } @@ -473,7 +473,7 @@ func (d *rangeDetacher) detachCNFCondAndBuildRangeForIndex(conditions []expressi accessConds = append(accessConds, cond) // TODO: if it's prefix column, we need to add cond to filterConds? } - ranges, accessConds, remainedConds, err = d.buildCNFIndexRange(tpSlice, eqOrInCount, accessConds) + ranges, accessConds, remainedConds, err = d.buildCNFIndexRange(newTpSlice, eqOrInCount, accessConds) if err != nil { return nil, err } @@ -608,7 +608,7 @@ func extractValueInfo(expr expression.Expression) *valueInfo { func ExtractEqAndInCondition(sctx sessionctx.Context, conditions []expression.Expression, cols []*expression.Column, lengths []int) ([]expression.Expression, []expression.Expression, []expression.Expression, []*valueInfo, bool) { var filters []expression.Expression - rb := builder{ctx: sctx} + rb := builder{sctx: sctx} accesses := make([]expression.Expression, len(cols)) points := make([][]*point, len(cols)) mergedAccesses := make([]expression.Expression, len(cols)) @@ -715,7 +715,7 @@ func (d *rangeDetacher) detachDNFCondAndBuildRangeForIndex(condition *expression optPrefixIndexSingleScan: d.sctx.GetSessionVars().OptPrefixIndexSingleScan, ctx: d.sctx, } - rb := builder{ctx: d.sctx} + rb := builder{sctx: d.sctx} dnfItems := expression.FlattenDNFConditions(condition) newAccessItems := make([]expression.Expression, 0, len(dnfItems)) var totalRanges Ranges diff --git a/pkg/util/ranger/points.go b/pkg/util/ranger/points.go index 439afedd68311..c93ac64dbf192 100644 --- a/pkg/util/ranger/points.go +++ b/pkg/util/ranger/points.go @@ -183,8 +183,8 @@ func NullRange() Ranges { // builder is the range builder struct. type builder struct { - err error - ctx sessionctx.Context + err error + sctx sessionctx.Context } // build converts Expression on one column into point, which can be further built into Range. @@ -193,7 +193,11 @@ type builder struct { // we pass it down from here. // If the input prefixLen is not types.UnspecifiedLength, it means it's for a prefix column in a prefix index. In such // cases, we should cut the prefix and adjust the exclusiveness. Ref: cutPrefixForPoints(). -func (r *builder) build(expr expression.Expression, collator collate.Collator, prefixLen int) []*point { +func (r *builder) build( + expr expression.Expression, + collator collate.Collator, + prefixLen int, +) []*point { switch x := expr.(type) { case *expression.Column: return r.buildFromColumn() @@ -207,7 +211,7 @@ func (r *builder) build(expr expression.Expression, collator collate.Collator, p } func (r *builder) buildFromConstant(expr *expression.Constant) []*point { - dt, err := expr.Eval(r.ctx, chunk.Row{}) + dt, err := expr.Eval(r.sctx, chunk.Row{}) if err != nil { r.err = err return nil @@ -216,7 +220,7 @@ func (r *builder) buildFromConstant(expr *expression.Constant) []*point { return nil } - tc := r.ctx.GetSessionVars().StmtCtx.TypeCtx() + tc := r.sctx.GetSessionVars().StmtCtx.TypeCtx() val, err := dt.ToBool(tc) if err != nil { r.err = err @@ -240,7 +244,10 @@ func (*builder) buildFromColumn() []*point { return []*point{startPoint1, endPoint1, startPoint2, endPoint2} } -func (r *builder) buildFromBinOp(expr *expression.ScalarFunction, prefixLen int) []*point { +func (r *builder) buildFromBinOp( + expr *expression.ScalarFunction, + prefixLen int, +) []*point { // This has been checked that the binary operation is comparison operation, and one of // the operand is column name expression. var ( @@ -250,7 +257,7 @@ func (r *builder) buildFromBinOp(expr *expression.ScalarFunction, prefixLen int) ft *types.FieldType ) - tc := r.ctx.GetSessionVars().StmtCtx.TypeCtx() + tc := r.sctx.GetSessionVars().StmtCtx.TypeCtx() // refineValueAndOp refines the constant datum and operator: // 1. for string type since we may eval the constant to another collation instead of its own collation. // 2. for year type since 2-digit year value need adjustment, see https://dev.mysql.com/doc/refman/5.6/en/year.html @@ -292,7 +299,7 @@ func (r *builder) buildFromBinOp(expr *expression.ScalarFunction, prefixLen int) var ok bool if col, ok = expr.GetArgs()[0].(*expression.Column); ok { ft = col.RetType - value, err = expr.GetArgs()[1].Eval(r.ctx, chunk.Row{}) + value, err = expr.GetArgs()[1].Eval(r.sctx, chunk.Row{}) if err != nil { return nil } @@ -303,7 +310,7 @@ func (r *builder) buildFromBinOp(expr *expression.ScalarFunction, prefixLen int) return nil } ft = col.RetType - value, err = expr.GetArgs()[0].Eval(r.ctx, chunk.Row{}) + value, err = expr.GetArgs()[0].Eval(r.sctx, chunk.Row{}) if err != nil { return nil } @@ -565,20 +572,23 @@ func (*builder) buildFromIsFalse(_ *expression.ScalarFunction, isNot int) []*poi return []*point{startPoint, endPoint} } -func (r *builder) buildFromIn(expr *expression.ScalarFunction, prefixLen int) ([]*point, bool) { +func (r *builder) buildFromIn( + expr *expression.ScalarFunction, + prefixLen int, +) ([]*point, bool) { list := expr.GetArgs()[1:] rangePoints := make([]*point, 0, len(list)*2) hasNull := false ft := expr.GetArgs()[0].GetType() colCollate := ft.GetCollate() - tc := r.ctx.GetSessionVars().StmtCtx.TypeCtx() + tc := r.sctx.GetSessionVars().StmtCtx.TypeCtx() for _, e := range list { v, ok := e.(*expression.Constant) if !ok { r.err = ErrUnsupportedType.GenWithStack("expr:%v is not constant", e) return getFullRange(), hasNull } - dt, err := v.Eval(r.ctx, chunk.Row{}) + dt, err := v.Eval(r.sctx, chunk.Row{}) if err != nil { r.err = ErrUnsupportedType.GenWithStack("expr:%v is not evaluated", e) return getFullRange(), hasNull @@ -648,12 +658,15 @@ func (r *builder) buildFromIn(expr *expression.ScalarFunction, prefixLen int) ([ return rangePoints, hasNull } -func (r *builder) newBuildFromPatternLike(expr *expression.ScalarFunction, prefixLen int) []*point { +func (r *builder) newBuildFromPatternLike( + expr *expression.ScalarFunction, + prefixLen int, +) []*point { _, collation := expr.CharsetAndCollation() if !collate.CompatibleCollate(expr.GetArgs()[0].GetType().GetCollate(), collation) { return getFullRange() } - pdt, err := expr.GetArgs()[1].(*expression.Constant).Eval(r.ctx, chunk.Row{}) + pdt, err := expr.GetArgs()[1].(*expression.Constant).Eval(r.sctx, chunk.Row{}) tpOfPattern := expr.GetArgs()[0].GetType() if err != nil { r.err = errors.Trace(err) @@ -671,7 +684,7 @@ func (r *builder) newBuildFromPatternLike(expr *expression.ScalarFunction, prefi return res } lowValue := make([]byte, 0, len(pattern)) - edt, err := expr.GetArgs()[2].(*expression.Constant).Eval(r.ctx, chunk.Row{}) + edt, err := expr.GetArgs()[2].(*expression.Constant).Eval(r.sctx, chunk.Row{}) if err != nil { r.err = errors.Trace(err) return getFullRange() @@ -751,7 +764,10 @@ func isPadSpaceCollation(collation string) bool { return collation != charset.CollationBin } -func (r *builder) buildFromNot(expr *expression.ScalarFunction, prefixLen int) []*point { +func (r *builder) buildFromNot( + expr *expression.ScalarFunction, + prefixLen int, +) []*point { switch n := expr.FuncName.L; n { case ast.IsTruthWithoutNull: return r.buildFromIsTrue(expr, 1, false) @@ -807,7 +823,11 @@ func (r *builder) buildFromNot(expr *expression.ScalarFunction, prefixLen int) [ return getFullRange() } -func (r *builder) buildFromScalarFunc(expr *expression.ScalarFunction, collator collate.Collator, prefixLen int) []*point { +func (r *builder) buildFromScalarFunc( + expr *expression.ScalarFunction, + collator collate.Collator, + prefixLen int, +) []*point { switch op := expr.FuncName.L; op { case ast.GE, ast.GT, ast.LT, ast.LE, ast.EQ, ast.NE, ast.NullEQ: return r.buildFromBinOp(expr, prefixLen) @@ -848,7 +868,7 @@ func (r *builder) union(a, b []*point, collator collate.Collator) []*point { func (r *builder) mergeSorted(a, b []*point, collator collate.Collator) []*point { ret := make([]*point, 0, len(a)+len(b)) i, j := 0, 0 - tc := r.ctx.GetSessionVars().StmtCtx.TypeCtx() + tc := r.sctx.GetSessionVars().StmtCtx.TypeCtx() for i < len(a) && j < len(b) { less, err := rangePointLess(tc, a[i], b[j], collator) if err != nil { diff --git a/pkg/util/ranger/ranger.go b/pkg/util/ranger/ranger.go index b74c948bac964..88af565795c19 100644 --- a/pkg/util/ranger/ranger.go +++ b/pkg/util/ranger/ranger.go @@ -60,13 +60,13 @@ func validInterval(sctx sessionctx.Context, low, high *point) (bool, error) { // convertPoints does some preprocessing on rangePoints to make them ready to build ranges. Preprocessing includes converting // points to the specified type, validating intervals and skipping impossible intervals. -func convertPoints(sctx sessionctx.Context, rangePoints []*point, tp *types.FieldType, skipNull bool, tableRange bool) ([]*point, error) { +func convertPoints(sctx sessionctx.Context, rangePoints []*point, newTp *types.FieldType, skipNull bool, tableRange bool) ([]*point, error) { i := 0 numPoints := len(rangePoints) var minValueDatum, maxValueDatum types.Datum if tableRange { // Currently, table's kv range cannot accept encoded value of MaxValueDatum. we need to convert it. - isUnsigned := mysql.HasUnsignedFlag(tp.GetFlag()) + isUnsigned := mysql.HasUnsignedFlag(newTp.GetFlag()) if isUnsigned { minValueDatum.SetUint64(0) maxValueDatum.SetUint64(math.MaxUint64) @@ -76,7 +76,7 @@ func convertPoints(sctx sessionctx.Context, rangePoints []*point, tp *types.Fiel } } for j := 0; j < numPoints; j += 2 { - startPoint, err := convertPoint(sctx, rangePoints[j], tp) + startPoint, err := convertPoint(sctx, rangePoints[j], newTp) if err != nil { return nil, errors.Trace(err) } @@ -88,7 +88,7 @@ func convertPoints(sctx sessionctx.Context, rangePoints []*point, tp *types.Fiel startPoint.value = minValueDatum } } - endPoint, err := convertPoint(sctx, rangePoints[j+1], tp) + endPoint, err := convertPoint(sctx, rangePoints[j+1], newTp) if err != nil { return nil, errors.Trace(err) } @@ -124,15 +124,15 @@ func estimateMemUsageForPoints2Ranges(rangePoints []*point) int64 { // Only one column is built there. If there're multiple columns, use appendPoints2Ranges. // rangeMaxSize is the max memory limit for ranges. O indicates no memory limit. // If the second return value is true, it means that the estimated memory usage of ranges exceeds rangeMaxSize and it falls back to full range. -func points2Ranges(sctx sessionctx.Context, rangePoints []*point, tp *types.FieldType, rangeMaxSize int64) (Ranges, bool, error) { - convertedPoints, err := convertPoints(sctx, rangePoints, tp, mysql.HasNotNullFlag(tp.GetFlag()), false) +func points2Ranges(sctx sessionctx.Context, rangePoints []*point, newTp *types.FieldType, rangeMaxSize int64) (Ranges, bool, error) { + convertedPoints, err := convertPoints(sctx, rangePoints, newTp, mysql.HasNotNullFlag(newTp.GetFlag()), false) if err != nil { return nil, false, errors.Trace(err) } // Estimate whether rangeMaxSize will be exceeded first before converting points to ranges. if rangeMaxSize > 0 && estimateMemUsageForPoints2Ranges(convertedPoints) > rangeMaxSize { var fullRange Ranges - if mysql.HasNotNullFlag(tp.GetFlag()) { + if mysql.HasNotNullFlag(newTp.GetFlag()) { fullRange = FullNotNullRange() } else { fullRange = FullRange() @@ -147,46 +147,46 @@ func points2Ranges(sctx sessionctx.Context, rangePoints []*point, tp *types.Fiel LowExclude: startPoint.excl, HighVal: []types.Datum{endPoint.value}, HighExclude: endPoint.excl, - Collators: []collate.Collator{collate.GetCollator(tp.GetCollate())}, + Collators: []collate.Collator{collate.GetCollator(newTp.GetCollate())}, } ranges = append(ranges, ran) } return ranges, false, nil } -func convertPoint(sctx sessionctx.Context, point *point, tp *types.FieldType) (*point, error) { +func convertPoint(sctx sessionctx.Context, point *point, newTp *types.FieldType) (*point, error) { sc := sctx.GetSessionVars().StmtCtx switch point.value.Kind() { case types.KindMaxValue, types.KindMinNotNull: return point, nil } - casted, err := point.value.ConvertTo(sc.TypeCtx(), tp) + casted, err := point.value.ConvertTo(sc.TypeCtx(), newTp) if err != nil { if sctx.GetSessionVars().StmtCtx.InPreparedPlanBuilding { // skip plan cache in this case for safety. sctx.GetSessionVars().StmtCtx.SetSkipPlanCache(errors.Errorf("%s when converting %v", err.Error(), point.value)) } //revive:disable:empty-block - if tp.GetType() == mysql.TypeYear && terror.ErrorEqual(err, types.ErrWarnDataOutOfRange) { + if newTp.GetType() == mysql.TypeYear && terror.ErrorEqual(err, types.ErrWarnDataOutOfRange) { // see issue #20101: overflow when converting integer to year - } else if tp.GetType() == mysql.TypeBit && terror.ErrorEqual(err, types.ErrDataTooLong) { + } else if newTp.GetType() == mysql.TypeBit && terror.ErrorEqual(err, types.ErrDataTooLong) { // see issue #19067: we should ignore the types.ErrDataTooLong when we convert value to TypeBit value - } else if tp.GetType() == mysql.TypeNewDecimal && terror.ErrorEqual(err, types.ErrOverflow) { + } else if newTp.GetType() == mysql.TypeNewDecimal && terror.ErrorEqual(err, types.ErrOverflow) { // Ignore the types.ErrOverflow when we convert TypeNewDecimal values. // A trimmed valid boundary point value would be returned then. Accordingly, the `excl` of the point // would be adjusted. Impossible ranges would be skipped by the `validInterval` call later. - } else if point.value.Kind() == types.KindMysqlTime && tp.GetType() == mysql.TypeTimestamp && terror.ErrorEqual(err, types.ErrWrongValue) { + } else if point.value.Kind() == types.KindMysqlTime && newTp.GetType() == mysql.TypeTimestamp && terror.ErrorEqual(err, types.ErrWrongValue) { // See issue #28424: query failed after add index // Ignore conversion from Date[Time] to Timestamp since it must be either out of range or impossible date, which will not match a point select - } else if tp.GetType() == mysql.TypeEnum && terror.ErrorEqual(err, types.ErrTruncated) { + } else if newTp.GetType() == mysql.TypeEnum && terror.ErrorEqual(err, types.ErrTruncated) { // Ignore the types.ErrorTruncated when we convert TypeEnum values. // We should cover Enum upper overflow, and convert to the biggest value. if point.value.GetInt64() > 0 { - upperEnum, err := types.ParseEnumValue(tp.GetElems(), uint64(len(tp.GetElems()))) + upperEnum, err := types.ParseEnumValue(newTp.GetElems(), uint64(len(newTp.GetElems()))) if err != nil { return nil, err } - casted.SetMysqlEnum(upperEnum, tp.GetCollate()) + casted.SetMysqlEnum(upperEnum, newTp.GetCollate()) } } else if terror.ErrorEqual(err, charset.ErrInvalidCharacterString) { // The invalid string can be produced by changing datum's underlying bytes directly. @@ -198,7 +198,7 @@ func convertPoint(sctx sessionctx.Context, point *point, tp *types.FieldType) (* } //revive:enable:empty-block } - valCmpCasted, err := point.value.Compare(sc.TypeCtx(), &casted, collate.GetCollator(tp.GetCollate())) + valCmpCasted, err := point.value.Compare(sc.TypeCtx(), &casted, collate.GetCollator(newTp.GetCollate())) if err != nil { return point, errors.Trace(err) } @@ -272,8 +272,8 @@ func estimateMemUsageForAppendPoints2Ranges(origin Ranges, rangePoints []*point) // If the second return value is true, it means that the estimated memory usage of ranges after appending points exceeds // rangeMaxSize and the function rejects appending points to ranges. func appendPoints2Ranges(sctx sessionctx.Context, origin Ranges, rangePoints []*point, - ft *types.FieldType, rangeMaxSize int64) (Ranges, bool, error) { - convertedPoints, err := convertPoints(sctx, rangePoints, ft, false, false) + newTp *types.FieldType, rangeMaxSize int64) (Ranges, bool, error) { + convertedPoints, err := convertPoints(sctx, rangePoints, newTp, false, false) if err != nil { return nil, false, errors.Trace(err) } @@ -287,7 +287,7 @@ func appendPoints2Ranges(sctx sessionctx.Context, origin Ranges, rangePoints []* if !oRange.IsPoint(sctx) { newIndexRanges = append(newIndexRanges, oRange) } else { - newRanges, err := appendPoints2IndexRange(oRange, convertedPoints, ft) + newRanges, err := appendPoints2IndexRange(oRange, convertedPoints, newTp) if err != nil { return nil, false, errors.Trace(err) } @@ -384,13 +384,13 @@ func AppendRanges2PointRanges(pointRanges Ranges, ranges Ranges, rangeMaxSize in // It will remove the nil and convert MinNotNull and MaxValue to MinInt64 or MinUint64 and MaxInt64 or MaxUint64. // rangeMaxSize is the max memory limit for ranges. O indicates no memory limit. // If the second return value is true, it means that the estimated memory usage of ranges exceeds rangeMaxSize and it falls back to full range. -func points2TableRanges(sctx sessionctx.Context, rangePoints []*point, tp *types.FieldType, rangeMaxSize int64) (Ranges, bool, error) { - convertedPoints, err := convertPoints(sctx, rangePoints, tp, true, true) +func points2TableRanges(sctx sessionctx.Context, rangePoints []*point, newTp *types.FieldType, rangeMaxSize int64) (Ranges, bool, error) { + convertedPoints, err := convertPoints(sctx, rangePoints, newTp, true, true) if err != nil { return nil, false, errors.Trace(err) } if rangeMaxSize > 0 && estimateMemUsageForPoints2Ranges(convertedPoints) > rangeMaxSize { - return FullIntRange(mysql.HasUnsignedFlag(tp.GetFlag())), true, nil + return FullIntRange(mysql.HasUnsignedFlag(newTp.GetFlag())), true, nil } ranges := make(Ranges, 0, len(convertedPoints)/2) for i := 0; i < len(convertedPoints); i += 2 { @@ -400,7 +400,7 @@ func points2TableRanges(sctx sessionctx.Context, rangePoints []*point, tp *types LowExclude: startPoint.excl, HighVal: []types.Datum{endPoint.value}, HighExclude: endPoint.excl, - Collators: []collate.Collator{collate.GetCollator(tp.GetCollate())}, + Collators: []collate.Collator{collate.GetCollator(newTp.GetCollate())}, } ranges = append(ranges, ran) } @@ -412,7 +412,7 @@ func points2TableRanges(sctx sessionctx.Context, rangePoints []*point, tp *types // The second return value is the conditions used to build ranges and the third return value is the remained conditions. func buildColumnRange(accessConditions []expression.Expression, sctx sessionctx.Context, tp *types.FieldType, tableRange bool, colLen int, rangeMaxSize int64) (Ranges, []expression.Expression, []expression.Expression, error) { - rb := builder{ctx: sctx} + rb := builder{sctx: sctx} rangePoints := getFullRange() for _, cond := range accessConditions { collator := collate.GetCollator(tp.GetCollate()) @@ -475,7 +475,7 @@ func BuildColumnRange(conds []expression.Expression, sctx sessionctx.Context, tp func (d *rangeDetacher) buildRangeOnColsByCNFCond(newTp []*types.FieldType, eqAndInCount int, accessConds []expression.Expression) (Ranges, []expression.Expression, []expression.Expression, error) { - rb := builder{ctx: d.sctx} + rb := builder{sctx: d.sctx} var ( ranges Ranges rangeFallback bool @@ -673,8 +673,10 @@ func ReachPrefixLen(v *types.Datum, length int, tp *types.FieldType) bool { return false } -// We cannot use the FieldType of column directly. e.g. the column a is int32 and we have a > 1111111111111111111. +// In util/ranger, for each datum that is used in the Range, we will convert data type for them. +// But we cannot use the FieldType of column directly. e.g. the column a is int32 and we have a > 1111111111111111111. // Obviously the constant is bigger than MaxInt32, so we will get overflow error if we use the FieldType of column a. +// In util/ranger here, we usually use "newTp" to emphasize its difference from the original FieldType of the column. func newFieldType(tp *types.FieldType) *types.FieldType { switch tp.GetType() { // To avoid overflow error. diff --git a/pkg/util/ranger/ranger_test.go b/pkg/util/ranger/ranger_test.go index 49c073ed9e570..0c8523255a836 100644 --- a/pkg/util/ranger/ranger_test.go +++ b/pkg/util/ranger/ranger_test.go @@ -1303,7 +1303,7 @@ create table t( exprStr: `e = "你好啊"`, accessConds: "[eq(test.t.e, 你好啊)]", filterConds: "[eq(test.t.e, 你好啊)]", - resultStr: "[[0xE4BD,0xE4BD]]", + resultStr: "[[\"\\xe4\\xbd\",\"\\xe4\\xbd\"]]", }, { indexPos: 2, @@ -1366,7 +1366,7 @@ create table t( exprStr: "d in ('aab', 'aac') and e = 'a'", accessConds: "[in(test.t.d, aab, aac) eq(test.t.e, a)]", filterConds: "[in(test.t.d, aab, aac)]", - resultStr: "[[\"aa\" 0x61,\"aa\" 0x61]]", + resultStr: "[[\"aa\" \"a\",\"aa\" \"a\"]]", }, { indexPos: 6, diff --git a/pkg/util/ranger/types.go b/pkg/util/ranger/types.go index 1ca9df2c7fb0f..f6eee7abdf774 100644 --- a/pkg/util/ranger/types.go +++ b/pkg/util/ranger/types.go @@ -271,7 +271,7 @@ func formatDatum(d types.Datum, isLeftSide bool) string { return "+inf" } case types.KindBytes: - return fmt.Sprintf("0x%X", d.GetValue()) + return fmt.Sprintf("%q", d.GetValue()) case types.KindString: return fmt.Sprintf("%q", d.GetValue()) case types.KindMysqlEnum, types.KindMysqlSet, diff --git a/tests/integrationtest/r/executor/point_get.result b/tests/integrationtest/r/executor/point_get.result index 0a3d08dd8465f..225902d8b71e0 100644 --- a/tests/integrationtest/r/executor/point_get.result +++ b/tests/integrationtest/r/executor/point_get.result @@ -256,21 +256,21 @@ set @@sql_mode=""; explain format='brief' select * from t where a = "a"; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:[0x61,0x61], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:["a","a"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo select * from t where a = "a"; a b explain format='brief' select * from t where a = "a "; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:[0x6120,0x6120], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:["a ","a "], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo select * from t where a = "a "; a b explain format='brief' select * from t where a = "a "; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:[0x612020,0x612020], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:["a ","a "], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo select * from t where a = "a "; a b @@ -278,7 +278,7 @@ explain format='brief' select hex(a), hex(b) from t where a = "a\0"; id estRows task access object operator info Projection 10.00 root hex(executor__point_get.t.a)->Column#4, hex(executor__point_get.t.b)->Column#5 └─IndexLookUp 10.00 root - ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:[0x6100,0x6100], keep order:false, stats:pseudo + ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:["a\x00","a\x00"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo select hex(a), hex(b) from t where a = "a\0"; hex(a) hex(b) @@ -287,21 +287,21 @@ set @@sql_mode=""; explain format='brief' select * from t tmp where a = "a"; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:tmp, index:idx_1(a) range:[0x61,0x61], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:tmp, index:idx_1(a) range:["a","a"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:tmp keep order:false, stats:pseudo select * from t tmp where a = "a"; a b explain format='brief' select * from t tmp where a = "a "; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:tmp, index:idx_1(a) range:[0x6120,0x6120], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:tmp, index:idx_1(a) range:["a ","a "], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:tmp keep order:false, stats:pseudo select * from t tmp where a = "a "; a b explain format='brief' select * from t tmp where a = "a "; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:tmp, index:idx_1(a) range:[0x612020,0x612020], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:tmp, index:idx_1(a) range:["a ","a "], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:tmp keep order:false, stats:pseudo select * from t tmp where a = "a "; a b @@ -309,7 +309,7 @@ explain format='brief' select hex(a), hex(b) from t tmp where a = "a\0"; id estRows task access object operator info Projection 10.00 root hex(executor__point_get.t.a)->Column#4, hex(executor__point_get.t.b)->Column#5 └─IndexLookUp 10.00 root - ├─IndexRangeScan(Build) 10.00 cop[tikv] table:tmp, index:idx_1(a) range:[0x6100,0x6100], keep order:false, stats:pseudo + ├─IndexRangeScan(Build) 10.00 cop[tikv] table:tmp, index:idx_1(a) range:["a\x00","a\x00"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:tmp keep order:false, stats:pseudo select hex(a), hex(b) from t tmp where a = "a\0"; hex(a) hex(b) @@ -318,14 +318,14 @@ insert into t values("a ", "b "); explain format='brief' select * from t where a = "a"; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:[0x61,0x61], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:["a","a"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo select * from t where a = "a"; a b explain format='brief' select * from t where a = "a "; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:[0x6120,0x6120], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:["a ","a "], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo select * from t where a = "a "; a b @@ -333,21 +333,21 @@ a b explain format='brief' select * from t where a = "a "; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:[0x612020,0x612020], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:["a ","a "], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo select * from t where a = "a "; a b explain format='brief' select * from t where a = "a"; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:[0x61,0x61], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:["a","a"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo select * from t where a = "a"; a b explain format='brief' select * from t where a = "a "; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:[0x6120,0x6120], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:["a ","a "], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo select * from t where a = "a "; a b @@ -355,7 +355,7 @@ a b explain format='brief' select * from t where a = "a "; id estRows task access object operator info IndexLookUp 10.00 root -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:[0x612020,0x612020], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_1(a) range:["a ","a "], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo select * from t where a = "a "; a b diff --git a/tests/integrationtest/r/explain_easy.result b/tests/integrationtest/r/explain_easy.result index bc4a5fa12ea69..1a200d1932a66 100644 --- a/tests/integrationtest/r/explain_easy.result +++ b/tests/integrationtest/r/explain_easy.result @@ -789,13 +789,13 @@ create table t(a binary(16) not null, b varchar(2) default null, c varchar(100) explain format = 'brief' select * from t where a=x'FA34E1093CB428485734E3917F000000' and b='xb'; id estRows task access object operator info IndexLookUp 0.10 root -├─IndexRangeScan(Build) 0.10 cop[tikv] table:t, index:a(a, b) range:[0xFA34E1093CB428485734E3917F000000 "xb",0xFA34E1093CB428485734E3917F000000 "xb"], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 0.10 cop[tikv] table:t, index:a(a, b) range:["\xfa4\xe1\t<\xb4(HW4\xe3\x91\x7f\x00\x00\x00" "xb","\xfa4\xe1\t<\xb4(HW4\xe3\x91\x7f\x00\x00\x00" "xb"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 0.10 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' update t set c = 'ssss' where a=x'FA34E1093CB428485734E3917F000000' and b='xb'; id estRows task access object operator info Update N/A root N/A └─IndexLookUp 0.10 root - ├─IndexRangeScan(Build) 0.10 cop[tikv] table:t, index:a(a, b) range:[0xFA34E1093CB428485734E3917F000000 "xb",0xFA34E1093CB428485734E3917F000000 "xb"], keep order:false, stats:pseudo + ├─IndexRangeScan(Build) 0.10 cop[tikv] table:t, index:a(a, b) range:["\xfa4\xe1\t<\xb4(HW4\xe3\x91\x7f\x00\x00\x00" "xb","\xfa4\xe1\t<\xb4(HW4\xe3\x91\x7f\x00\x00\x00" "xb"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 0.10 cop[tikv] table:t keep order:false, stats:pseudo drop table if exists t; create table t(a int, b int); diff --git a/tests/integrationtest/r/expression/charset_and_collation.result b/tests/integrationtest/r/expression/charset_and_collation.result index 99e6bd15af159..c4764744183e6 100644 --- a/tests/integrationtest/r/expression/charset_and_collation.result +++ b/tests/integrationtest/r/expression/charset_and_collation.result @@ -1916,7 +1916,7 @@ a explain format="brief" select v from t_bin where v < 'b' order by v; id estRows task access object operator info IndexReader 3323.33 root index:IndexRangeScan -└─IndexRangeScan 3323.33 cop[tikv] table:t_bin, index:v(v) range:[-inf,0x62), keep order:true, stats:pseudo +└─IndexRangeScan 3323.33 cop[tikv] table:t_bin, index:v(v) range:[-inf,"b"), keep order:true, stats:pseudo select v from t_bin where v < 'b' order by v; v @@ -1924,7 +1924,7 @@ a explain format="brief" select v from t_bin where v < 'b' and v > ' ' order by v; id estRows task access object operator info IndexReader 250.00 root index:IndexRangeScan -└─IndexRangeScan 250.00 cop[tikv] table:t_bin, index:v(v) range:(0x20,0x62), keep order:true, stats:pseudo +└─IndexRangeScan 250.00 cop[tikv] table:t_bin, index:v(v) range:(" ","b"), keep order:true, stats:pseudo select v from t_bin where v < 'b' and v > ' ' order by v; v a @@ -1957,7 +1957,7 @@ explain format="brief" select id from t_bin use index(v) where v < 'b'; id estRows task access object operator info Projection 3323.33 root expression__charset_and_collation.t_bin.id └─IndexLookUp 3323.33 root - ├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t_bin, index:v(v) range:[-inf,0x62), keep order:false, stats:pseudo + ├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t_bin, index:v(v) range:[-inf,"b"), keep order:false, stats:pseudo └─TableRowIDScan(Probe) 3323.33 cop[tikv] table:t_bin keep order:false, stats:pseudo select id from t_bin use index(v) where v < 'b'; id @@ -1967,7 +1967,7 @@ explain format="brief" select id from t_bin use index(v) where v < 'b' and v > ' id estRows task access object operator info Projection 250.00 root expression__charset_and_collation.t_bin.id └─IndexLookUp 250.00 root - ├─IndexRangeScan(Build) 250.00 cop[tikv] table:t_bin, index:v(v) range:(0x20,0x62), keep order:false, stats:pseudo + ├─IndexRangeScan(Build) 250.00 cop[tikv] table:t_bin, index:v(v) range:(" ","b"), keep order:false, stats:pseudo └─TableRowIDScan(Probe) 250.00 cop[tikv] table:t_bin keep order:false, stats:pseudo select id from t_bin use index(v) where v < 'b' and v > ' '; id diff --git a/tests/integrationtest/r/expression/issues.result b/tests/integrationtest/r/expression/issues.result index f83efc641ffb1..0e22481096b0d 100644 --- a/tests/integrationtest/r/expression/issues.result +++ b/tests/integrationtest/r/expression/issues.result @@ -2106,7 +2106,7 @@ insert into t values('`?'); explain format='brief' select * from t where a like '`%'; id estRows task access object operator info TableReader 250.00 root data:TableRangeScan -└─TableRangeScan 250.00 cop[tikv] table:t range:[0x60,0x61), keep order:false, stats:pseudo +└─TableRangeScan 250.00 cop[tikv] table:t range:["`","a"), keep order:false, stats:pseudo select * from t where a like '`%'; a `? diff --git a/tests/integrationtest/r/planner/core/casetest/rule/rule_derive_topn_from_window.result b/tests/integrationtest/r/planner/core/casetest/rule/rule_derive_topn_from_window.result index 3e1005263bc9d..dfa248d4e8880 100644 --- a/tests/integrationtest/r/planner/core/casetest/rule/rule_derive_topn_from_window.result +++ b/tests/integrationtest/r/planner/core/casetest/rule/rule_derive_topn_from_window.result @@ -289,7 +289,7 @@ Sort 0.89 root planner__core__casetest__rule__rule_derive_topn_from_window.cust └─TableReader 1.11 root data:TopN └─TopN 1.11 cop[tikv] partition by planner__core__casetest__rule__rule_derive_topn_from_window.customer.primary_key, planner__core__casetest__rule__rule_derive_topn_from_window.customer.secondary_key order by planner__core__casetest__rule__rule_derive_topn_from_window.customer.c_timestamp, offset:0, count:10 └─Selection 1.11 cop[tikv] ge(planner__core__casetest__rule__rule_derive_topn_from_window.customer.c_timestamp, 1661883508511000000) - └─TableRangeScan 33.33 cop[tikv] table:customer range:[0x0002 0x0001,0x0002 +inf], keep order:false, stats:pseudo + └─TableRangeScan 33.33 cop[tikv] table:customer range:["\x00\x02" "\x00\x01","\x00\x02" +inf], keep order:false, stats:pseudo select * from (select *, row_number() over (partition by primary_key, secondary_key order by c_timestamp) as rownum from customer where primary_key = 0x002 and secondary_key >= 0x001 and c_timestamp >= 1661883508511000000) as nested where rownum <= 10 order by secondary_key desc; primary_key secondary_key c_timestamp value rownum explain format = 'brief' select * from (select row_number() over (partition by b) as rownumber from td) DT where rownumber <= 1 -- pattern is applicable with partition by prefix of primary key; diff --git a/tests/integrationtest/r/planner/core/indexmerge_path.result b/tests/integrationtest/r/planner/core/indexmerge_path.result index 5d9692411d014..2c15dcaea6556 100644 --- a/tests/integrationtest/r/planner/core/indexmerge_path.result +++ b/tests/integrationtest/r/planner/core/indexmerge_path.result @@ -186,44 +186,44 @@ Selection 8.00 root json_overlaps(cast("1", json BINARY), json_extract(planner_ explain format = 'brief' select /*+ use_index_merge(t, j0_string) */ * from t where ("a" member of (j0->'$.path_string')); id estRows task access object operator info IndexMerge 10.00 root type: union -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x61,0x61], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["a","a"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select /*+ use_index_merge(t, j0_string) */ * from t where ("a" member of (j0->'$.path_string')) and a<10; id estRows task access object operator info IndexMerge 3.32 root type: union -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x61,0x61], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["a","a"], keep order:false, stats:pseudo └─Selection(Probe) 3.32 cop[tikv] lt(planner__core__indexmerge_path.t.a, 10) └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select /*+ use_index_merge(t, j0_string) */ * from t where json_contains((j0->'$.path_string'), '["a", "b", "c"]'); id estRows task access object operator info IndexMerge 10.00 root type: intersection -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x61,0x61], keep order:false, stats:pseudo -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x62,0x62], keep order:false, stats:pseudo -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x63,0x63], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["a","a"], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["b","b"], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["c","c"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select /*+ use_index_merge(t, j0_string) */ * from t where json_contains((j0->'$.path_string'), '["a", "b", "c"]') and a<10; id estRows task access object operator info IndexMerge 3.32 root type: intersection -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x61,0x61], keep order:false, stats:pseudo -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x62,0x62], keep order:false, stats:pseudo -├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x63,0x63], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["a","a"], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["b","b"], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["c","c"], keep order:false, stats:pseudo └─Selection(Probe) 3.32 cop[tikv] lt(planner__core__indexmerge_path.t.a, 10) └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select /*+ use_index_merge(t, j0_string) */ * from t where json_overlaps((j0->'$.path_string'), '["a", "b", "c"]'); id estRows task access object operator info Selection 8.00 root json_overlaps(json_extract(planner__core__indexmerge_path.t.j0, "$.path_string"), cast("["a", "b", "c"]", json BINARY)) └─IndexMerge 10.00 root type: union - ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x61,0x61], keep order:false, stats:pseudo - ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x62,0x62], keep order:false, stats:pseudo - ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x63,0x63], keep order:false, stats:pseudo + ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["a","a"], keep order:false, stats:pseudo + ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["b","b"], keep order:false, stats:pseudo + ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["c","c"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select /*+ use_index_merge(t, j0_string) */ * from t where json_overlaps((j0->'$.path_string'), '["a", "b", "c"]') and a<10; id estRows task access object operator info Selection 8.00 root json_overlaps(json_extract(planner__core__indexmerge_path.t.j0, "$.path_string"), cast("["a", "b", "c"]", json BINARY)) └─IndexMerge 3.32 root type: union - ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x61,0x61], keep order:false, stats:pseudo - ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x62,0x62], keep order:false, stats:pseudo - ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:[0x63,0x63], keep order:false, stats:pseudo + ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["a","a"], keep order:false, stats:pseudo + ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["b","b"], keep order:false, stats:pseudo + ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_string(cast(json_extract(`j0`, _utf8mb4'$.path_string') as char(10) array)) range:["c","c"], keep order:false, stats:pseudo └─Selection(Probe) 3.32 cop[tikv] lt(planner__core__indexmerge_path.t.a, 10) └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select /*+ use_index_merge(t, j0_date) */ * from t where ("2023-01-01" member of (j0->'$.path_date')); @@ -355,12 +355,12 @@ IndexMerge 10.00 root type: union explain format = 'brief' select /*+ use_index_merge(t, idx2) */ * from t where a=1 and b=2 and ('3' member of (j->'$.str')) and c=4; id estRows task access object operator info IndexMerge 0.00 root type: union -├─IndexRangeScan(Build) 0.00 cop[tikv] table:t, index:idx2(a, b, cast(json_extract(`j`, _utf8mb4'$.str') as char(10) array), c) range:[1 2 0x33 4,1 2 0x33 4], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 0.00 cop[tikv] table:t, index:idx2(a, b, cast(json_extract(`j`, _utf8mb4'$.str') as char(10) array), c) range:[1 2 "3" 4,1 2 "3" 4], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 0.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select /*+ use_index_merge(t, idx2) */ * from t where a=1 and b=2 and ('3' member of (j->'$.str')); id estRows task access object operator info IndexMerge 0.00 root type: union -├─IndexRangeScan(Build) 0.00 cop[tikv] table:t, index:idx2(a, b, cast(json_extract(`j`, _utf8mb4'$.str') as char(10) array), c) range:[1 2 0x33,1 2 0x33], keep order:false, stats:pseudo +├─IndexRangeScan(Build) 0.00 cop[tikv] table:t, index:idx2(a, b, cast(json_extract(`j`, _utf8mb4'$.str') as char(10) array), c) range:[1 2 "3",1 2 "3"], keep order:false, stats:pseudo └─TableRowIDScan(Probe) 0.00 cop[tikv] table:t keep order:false, stats:pseudo explain format = 'brief' select /*+ use_index_merge(t, idx2) */ * from t where a=1 and b=2; id estRows task access object operator info diff --git a/tests/integrationtest/r/planner/core/range_scan_for_like.result b/tests/integrationtest/r/planner/core/range_scan_for_like.result new file mode 100644 index 0000000000000..7dfdb7e8fb116 --- /dev/null +++ b/tests/integrationtest/r/planner/core/range_scan_for_like.result @@ -0,0 +1,999 @@ +create table t(a varchar(20) collate utf8mb4_general_ci, index ia(a)); +insert into t value('测试'),('测试Abc'),('测试 '),('你好'),('aABBccdd'),('Aa'),(''),(' '),(' '),(' 语言'),(' 语 言 '),('测测试 '),('测测试 '),(NULL); +explain select *, length(a) from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试%", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +a length(a) +测试 6 +测试 11 +测试Abc 9 +explain select *, length(a) from t use index (ia) where a like '测%%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测%%", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like '测%%' order by a,_tidb_rowid; +a length(a) +测测试 10 +测测试 13 +测试 6 +测试 11 +测试Abc 9 +explain select *, length(a) from t use index (ia) where a like '测%%试' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测%%试", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like '测%%试' order by a,_tidb_rowid; +a length(a) +测试 6 +explain select *, length(a) from t use index (ia) where a like '测试%%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试%%", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like '测试%%' order by a,_tidb_rowid; +a length(a) +测试 6 +测试 11 +测试Abc 9 +explain select *, length(a) from t use index (ia) where a like '测试_' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试_", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like '测试_' order by a,_tidb_rowid; +a length(a) +explain select *, length(a) from t use index (ia) where a like '你好%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "你好%", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like '你好%' order by a,_tidb_rowid; +a length(a) +你好 6 +explain select *, length(a) from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +a length(a) +Aa 2 +explain select *, length(a) from t use index (ia) where a like 'aa%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa%", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa%' order by a,_tidb_rowid; +a length(a) +Aa 2 +aABBccdd 8 +explain select *, length(a) from t use index (ia) where a like 'aa%cc' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa%cc", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa%cc' order by a,_tidb_rowid; +a length(a) +explain select *, length(a) from t use index (ia) where a like '' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like '' order by a,_tidb_rowid; +a length(a) + 0 +explain select *, length(a) from t use index (ia) where a like ' ' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " ", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like ' ' order by a,_tidb_rowid; +a length(a) + 1 +explain select *, length(a) from t use index (ia) where a like 'aa%dd' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa%dd", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa%dd' order by a,_tidb_rowid; +a length(a) +aABBccdd 8 +explain select *, length(a) from t use index (ia) where a like 'aa%%dd' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa%%dd", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa%%dd' order by a,_tidb_rowid; +a length(a) +aABBccdd 8 +explain select *, length(a) from t use index (ia) where a like 'aa_bccdd' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa_bccdd", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa_bccdd' order by a,_tidb_rowid; +a length(a) +aABBccdd 8 +explain select *, length(a) from t use index (ia) where a like '%%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "%%", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like '%%' order by a,_tidb_rowid; +a length(a) + 0 + 1 + 2 + 语 言 10 + 语言 7 +Aa 2 +aABBccdd 8 +你好 6 +测测试 10 +测测试 13 +测试 6 +测试 11 +测试Abc 9 +explain select *, length(a) from t use index (ia) where a like ' %%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " %%", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like ' %%' order by a,_tidb_rowid; +a length(a) + 1 + 2 + 语 言 10 + 语言 7 +explain select *, length(a) from t use index (ia) where a like ' %%语言' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " %%语言", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like ' %%语言' order by a,_tidb_rowid; +a length(a) + 语言 7 +explain select *, length(a) from t use index (ia) where a like ' 语 %' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " 语 %", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like ' 语 %' order by a,_tidb_rowid; +a length(a) + 语 言 10 +explain select *, length(a) from t use index (ia) where a like ' 语 _' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Projection_13 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_16 8000.00 root index:Selection_15 + └─Selection_15 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " 语 _", 92) + └─IndexFullScan_14 10000.00 cop[tikv] table:t, index:ia(a) keep order:true, stats:pseudo +select *, length(a) from t use index (ia) where a like ' 语 _' order by a,_tidb_rowid; +a length(a) +drop table t; +create table t(a varchar(20) collate utf8mb4_unicode_ci, unique index ia(a)); +insert into t value(''),('测试'),('测试abc'),('你好'),('aabbccdd'),(' 语言'),(' 语 言 '),('测测试 '); +explain select *, length(a) from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试%", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +a length(a) +测试 6 +测试abc 9 +explain select *, length(a) from t use index (ia) where a like '测%%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测%%", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like '测%%' order by a,_tidb_rowid; +a length(a) +测测试 13 +测试 6 +测试abc 9 +explain select *, length(a) from t use index (ia) where a like '测%%试' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测%%试", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like '测%%试' order by a,_tidb_rowid; +a length(a) +测试 6 +explain select *, length(a) from t use index (ia) where a like '测试%%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试%%", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like '测试%%' order by a,_tidb_rowid; +a length(a) +测试 6 +测试abc 9 +explain select *, length(a) from t use index (ia) where a like '测试_' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试_", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like '测试_' order by a,_tidb_rowid; +a length(a) +explain select *, length(a) from t use index (ia) where a like '你好%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "你好%", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like '你好%' order by a,_tidb_rowid; +a length(a) +你好 6 +explain select *, length(a) from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +a length(a) +explain select *, length(a) from t use index (ia) where a like 'aa%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa%", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa%' order by a,_tidb_rowid; +a length(a) +aabbccdd 8 +explain select *, length(a) from t use index (ia) where a like 'aa%cc' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa%cc", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa%cc' order by a,_tidb_rowid; +a length(a) +explain select *, length(a) from t use index (ia) where a like '' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like '' order by a,_tidb_rowid; +a length(a) + 0 +explain select *, length(a) from t use index (ia) where a like 'aa%dd' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa%dd", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa%dd' order by a,_tidb_rowid; +a length(a) +aabbccdd 8 +explain select *, length(a) from t use index (ia) where a like 'aa%%dd' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa%%dd", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa%%dd' order by a,_tidb_rowid; +a length(a) +aabbccdd 8 +explain select *, length(a) from t use index (ia) where a like 'aa_bccdd' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa_bccdd", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like 'aa_bccdd' order by a,_tidb_rowid; +a length(a) +aabbccdd 8 +explain select *, length(a) from t use index (ia) where a like '%%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "%%", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like '%%' order by a,_tidb_rowid; +a length(a) + 0 + 语 言 10 + 语言 7 +aabbccdd 8 +你好 6 +测测试 13 +测试 6 +测试abc 9 +explain select *, length(a) from t use index (ia) where a like ' %%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " %%", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like ' %%' order by a,_tidb_rowid; +a length(a) + 语 言 10 + 语言 7 +explain select *, length(a) from t use index (ia) where a like ' %%语言' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " %%语言", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like ' %%语言' order by a,_tidb_rowid; +a length(a) + 语言 7 +explain select *, length(a) from t use index (ia) where a like ' 语 %' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " 语 %", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like ' 语 %' order by a,_tidb_rowid; +a length(a) + 语 言 10 +explain select *, length(a) from t use index (ia) where a like ' 语 _' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, Column#3->Column#5 +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─Projection_9 8000.00 root planner__core__range_scan_for_like.t.a, length(planner__core__range_scan_for_like.t.a)->Column#3, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexReader_12 8000.00 root index:Selection_11 + └─Selection_11 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " 语 _", 92) + └─IndexFullScan_10 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo +select *, length(a) from t use index (ia) where a like ' 语 _' order by a,_tidb_rowid; +a length(a) +drop table t; +create table t(a varchar(20) collate utf8mb4_0900_ai_ci, b varchar(20) collate ascii_bin, c bigint, primary key(a(1), b) clustered); +insert into t (a, b, c) values +('测试1', 'asdfgh', 345346), +('你好2', 'qqwweerrrr', 987765), +('こんにちは3', 'zxcvbnn', 1111111), +('안녕하세요4', 'asdfgh ', 3333333333), +('Ciao5', ' asdfgh', 444400), +('Hola6', ' asdfgh ', 6666), +('Bonjour ', '', 888888888), +('Olá8', ' ', 9999999), +('Привет9', ' ', 321321), +('Hallo10', '12345', 35678); +explain select * from t use index (primary) where a like '测试%' and b like 'asd%' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─TableReader_10 200.00 root data:Selection_9 + └─Selection_9 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试%", 92), like(planner__core__range_scan_for_like.t.b, "asd%", 92) + └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like '测试%' and b like 'asd%' order by a,b; +a b c +测试1 asdfgh 345346 +explain select * from t use index (primary) where a like '测试1' and b like 'asdfgh %' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─TableReader_10 200.00 root data:Selection_9 + └─Selection_9 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试1", 92), like(planner__core__range_scan_for_like.t.b, "asdfgh %", 92) + └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like '测试1' and b like 'asdfgh %' order by a,b; +a b c +explain select * from t use index (primary) where a like 'こんにち_' and b like 'zxc%' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─TableReader_10 200.00 root data:Selection_9 + └─Selection_9 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "こんにち_", 92), like(planner__core__range_scan_for_like.t.b, "zxc%", 92) + └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like 'こんにち_' and b like 'zxc%' order by a,b; +a b c +explain select * from t use index (primary) where a like '안녕하세요%' and b like 'asd%' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─TableReader_10 200.00 root data:Selection_9 + └─Selection_9 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "안녕하세요%", 92), like(planner__core__range_scan_for_like.t.b, "asd%", 92) + └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like '안녕하세요%' and b like 'asd%' order by a,b; +a b c +안녕하세요4 asdfgh 3333333333 +explain select * from t use index (primary) where a like 'Ciáo%' and b like ' _%' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─TableReader_10 200.00 root data:Selection_9 + └─Selection_9 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "Ciáo%", 92), like(planner__core__range_scan_for_like.t.b, " _%", 92) + └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like 'Ciáo%' and b like ' _%' order by a,b; +a b c +Ciao5 asdfgh 444400 +explain select * from t use index (primary) where a like '%HoLa%' and b like ' asdfgh' order by a,b; +id estRows task access object operator info +Sort_5 8.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─TableReader_10 8.00 root data:Selection_9 + └─Selection_9 8.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "%HoLa%", 92), like(planner__core__range_scan_for_like.t.b, " asdfgh", 92) + └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like '%HoLa%' and b like ' asdfgh' order by a,b; +a b c +explain select * from t use index (primary) where a like 'bonjour _%' and b like '' order by a,b; +id estRows task access object operator info +Sort_5 8.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─TableReader_10 8.00 root data:Selection_9 + └─Selection_9 8.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "bonjour _%", 92), like(planner__core__range_scan_for_like.t.b, "", 92) + └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like 'bonjour _%' and b like '' order by a,b; +a b c +Bonjour 888888888 +explain select * from t use index (primary) where a like 'OLa%' and b like '_' order by a,b; +id estRows task access object operator info +Sort_5 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─TableReader_10 8000.00 root data:Selection_9 + └─Selection_9 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "OLa%", 92), like(planner__core__range_scan_for_like.t.b, "_", 92) + └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like 'OLa%' and b like '_' order by a,b; +a b c +Olá8 9999999 +explain select * from t use index (primary) where a like 'Приве__' and b like ' %' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─TableReader_10 200.00 root data:Selection_9 + └─Selection_9 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "Приве__", 92), like(planner__core__range_scan_for_like.t.b, " %", 92) + └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like 'Приве__' and b like ' %' order by a,b; +a b c +Привет9 321321 +explain select * from t use index (primary) where a like 'Hallo%' and b like '123%' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─TableReader_10 200.00 root data:Selection_9 + └─Selection_9 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "Hallo%", 92), like(planner__core__range_scan_for_like.t.b, "123%", 92) + └─TableFullScan_8 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like 'Hallo%' and b like '123%' order by a,b; +a b c +Hallo10 12345 35678 +drop table t; +create table t(a varchar(20) collate gbk_chinese_ci, b varchar(20) collate latin1_bin, c bigint, primary key(a, b(5)) nonclustered); +insert into t (a, b, c) values +('测试1', 'asdfgh', 345346), +('你好2', 'qqwweerrrr', 987765), +('zxcvbnn',0xE38193E38293E381ABE381A1E381AF33, 1111111), +('asdfgh ', 0xEC9588EB8595ED9598EC84B8EC9A9434, 3333333333), +('Ciao5', ' asdfgh', 444400), +(' asdfgh ', 'Hola6', 6666), +('Bonjour ', '', 888888888), +('Olá8', ' ', 9999999), +('Привет9', ' ', 321321), +(' ', '12345', 35678); +set names utf8mb4; +explain select * from t use index (primary) where a like '测试%' and b like 'asd%' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─IndexLookUp_12 200.00 root + ├─Selection_10(Build) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试%", 92) + │ └─IndexFullScan_8 10000.00 cop[tikv] table:t, index:PRIMARY(a, b) keep order:false, stats:pseudo + └─Selection_11(Probe) 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.b, "asd%", 92) + └─TableRowIDScan_9 8000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like '测试%' and b like 'asd%' order by a,b; +a b c +测试1 asdfgh 345346 +explain select * from t use index (primary) where a like '测试1' and b like 'asdfgh %' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─IndexLookUp_12 200.00 root + ├─Selection_10(Build) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试1", 92) + │ └─IndexFullScan_8 10000.00 cop[tikv] table:t, index:PRIMARY(a, b) keep order:false, stats:pseudo + └─Selection_11(Probe) 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.b, "asdfgh %", 92) + └─TableRowIDScan_9 8000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like '测试1' and b like 'asdfgh %' order by a,b; +a b c +set names latin1; +explain select * from t use index (primary) where b like 'こんにち_' and a like 'zxc%' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─IndexLookUp_12 200.00 root + ├─Selection_10(Build) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "zxc%", 92) + │ └─IndexFullScan_8 10000.00 cop[tikv] table:t, index:PRIMARY(a, b) keep order:false, stats:pseudo + └─Selection_11(Probe) 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.b, "こんにち_", 92) + └─TableRowIDScan_9 8000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where b like 'こんにち_' and a like 'zxc%' order by a,b; +a b c +explain select * from t use index (primary) where b like '안녕하세요%' and a like 'asd%' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─IndexLookUp_12 200.00 root + ├─Selection_10(Build) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "asd%", 92) + │ └─IndexFullScan_8 10000.00 cop[tikv] table:t, index:PRIMARY(a, b) keep order:false, stats:pseudo + └─Selection_11(Probe) 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.b, "안녕하세요%", 92) + └─TableRowIDScan_9 8000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where b like '안녕하세요%' and a like 'asd%' order by a,b; +a b c +asdfgh 안녕하세요4 3333333333 +set names utf8mb4; +explain select * from t use index (primary) where a like 'Ciao%' and b like ' _%' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─IndexLookUp_12 200.00 root + ├─Selection_10(Build) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "Ciao%", 92) + │ └─IndexFullScan_8 10000.00 cop[tikv] table:t, index:PRIMARY(a, b) keep order:false, stats:pseudo + └─Selection_11(Probe) 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.b, " _%", 92) + └─TableRowIDScan_9 8000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like 'Ciao%' and b like ' _%' order by a,b; +a b c +Ciao5 asdfgh 444400 +explain select * from t use index (primary) where b like 'HoLa%' and a like ' asdfgh' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─IndexLookUp_12 200.00 root + ├─Selection_10(Build) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " asdfgh", 92) + │ └─IndexFullScan_8 10000.00 cop[tikv] table:t, index:PRIMARY(a, b) keep order:false, stats:pseudo + └─Selection_11(Probe) 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.b, "HoLa%", 92) + └─TableRowIDScan_9 8000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where b like 'HoLa%' and a like ' asdfgh' order by a,b; +a b c +explain select * from t use index (primary) where a like 'bonjour _%' and b like '' order by a,b; +id estRows task access object operator info +Sort_5 8.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─IndexLookUp_12 8.00 root + ├─Selection_10(Build) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "bonjour _%", 92) + │ └─IndexFullScan_8 10000.00 cop[tikv] table:t, index:PRIMARY(a, b) keep order:false, stats:pseudo + └─Selection_11(Probe) 8.00 cop[tikv] like(planner__core__range_scan_for_like.t.b, "", 92) + └─TableRowIDScan_9 8000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like 'bonjour _%' and b like '' order by a,b; +a b c +Bonjour 888888888 +explain select * from t use index (primary) where a like 'OLá' and b like '_' order by a,b; +id estRows task access object operator info +Sort_5 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─IndexLookUp_12 8000.00 root + ├─Selection_10(Build) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "OLá", 92) + │ └─IndexFullScan_8 10000.00 cop[tikv] table:t, index:PRIMARY(a, b) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.b, "_", 92) + └─TableRowIDScan_9 8000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like 'OLá' and b like '_' order by a,b; +a b c +explain select * from t use index (primary) where a like 'Приве__' and b like ' %' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─IndexLookUp_12 200.00 root + ├─Selection_10(Build) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "Приве__", 92) + │ └─IndexFullScan_8 10000.00 cop[tikv] table:t, index:PRIMARY(a, b) keep order:false, stats:pseudo + └─Selection_11(Probe) 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.b, " %", 92) + └─TableRowIDScan_9 8000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like 'Приве__' and b like ' %' order by a,b; +a b c +Привет9 321321 +explain select * from t use index (primary) where a like ' %' and b like '123%' order by a,b; +id estRows task access object operator info +Sort_5 200.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─IndexLookUp_12 200.00 root + ├─Selection_10(Build) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " %", 92) + │ └─IndexFullScan_8 10000.00 cop[tikv] table:t, index:PRIMARY(a, b) keep order:false, stats:pseudo + └─Selection_11(Probe) 200.00 cop[tikv] like(planner__core__range_scan_for_like.t.b, "123%", 92) + └─TableRowIDScan_9 8000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (primary) where a like ' %' and b like '123%' order by a,b; +a b c + 12345 35678 +drop table t; +create table t(a varchar(20) collate utf8mb4_general_ci, b bigint, index ia(a(3))); +insert into t value +('测试',222), +('测试Abc',324), +('测试 ',543), +('你好',111), +('aABBccdd',890), +('A',456), +('Aa',456), +('aab',456), +('aabB',456), +('',234), +(' ',11111), +(' ',66666), +(' 语言',55555), +(' 语 言',3579), +('测测试 ',2468), +('测测试 ',99999), +(NULL,10); +explain select * from t use index (ia) where a > 'aabb' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 3333.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 3333.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 3333.33 root + ├─IndexRangeScan_9(Build) 3333.33 cop[tikv] table:t, index:ia(a) range:["aab",+inf], keep order:false, stats:pseudo + └─Selection_11(Probe) 3333.33 cop[tikv] gt(planner__core__range_scan_for_like.t.a, "aabb") + └─TableRowIDScan_10 3333.33 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a > 'aabb' order by a,_tidb_rowid; +a b +aABBccdd 890 +你好 111 +测测试 2468 +测测试 99999 +测试 222 +测试 543 +测试Abc 324 +explain select * from t use index (ia) where a > 'aab' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 3333.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 3333.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 3333.33 root + ├─IndexRangeScan_9(Build) 3333.33 cop[tikv] table:t, index:ia(a) range:["aab",+inf], keep order:false, stats:pseudo + └─Selection_11(Probe) 3333.33 cop[tikv] gt(planner__core__range_scan_for_like.t.a, "aab") + └─TableRowIDScan_10 3333.33 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a > 'aab' order by a,_tidb_rowid; +a b +aabB 456 +aABBccdd 890 +你好 111 +测测试 2468 +测测试 99999 +测试 222 +测试 543 +测试Abc 324 +explain select * from t use index (ia) where a > 'aa' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 3333.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 3333.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 3333.33 root + ├─IndexRangeScan_9(Build) 3333.33 cop[tikv] table:t, index:ia(a) range:("aa",+inf], keep order:false, stats:pseudo + └─Selection_11(Probe) 3333.33 cop[tikv] gt(planner__core__range_scan_for_like.t.a, "aa") + └─TableRowIDScan_10 3333.33 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a > 'aa' order by a,_tidb_rowid; +a b +aab 456 +aabB 456 +aABBccdd 890 +你好 111 +测测试 2468 +测测试 99999 +测试 222 +测试 543 +测试Abc 324 +explain select * from t use index (ia) where a < 'aabb' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 3323.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 3323.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 3323.33 root + ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t, index:ia(a) range:[-inf,"aab"], keep order:false, stats:pseudo + └─Selection_11(Probe) 3323.33 cop[tikv] lt(planner__core__range_scan_for_like.t.a, "aabb") + └─TableRowIDScan_10 3323.33 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a < 'aabb' order by a,_tidb_rowid; +a b + 234 + 11111 + 66666 + 语 言 3579 + 语言 55555 +A 456 +Aa 456 +aab 456 +explain select * from t use index (ia) where a < 'aab' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 3323.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 3323.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 3323.33 root + ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t, index:ia(a) range:[-inf,"aab"), keep order:false, stats:pseudo + └─Selection_11(Probe) 3323.33 cop[tikv] lt(planner__core__range_scan_for_like.t.a, "aab") + └─TableRowIDScan_10 3323.33 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a < 'aab' order by a,_tidb_rowid; +a b + 234 + 11111 + 66666 + 语 言 3579 + 语言 55555 +A 456 +Aa 456 +explain select * from t use index (ia) where a < 'aa' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 3323.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 3323.33 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 3323.33 root + ├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t, index:ia(a) range:[-inf,"aa"), keep order:false, stats:pseudo + └─Selection_11(Probe) 3323.33 cop[tikv] lt(planner__core__range_scan_for_like.t.a, "aa") + └─TableRowIDScan_10 3323.33 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a < 'aa' order by a,_tidb_rowid; +a b + 234 + 11111 + 66666 + 语 言 3579 + 语言 55555 +A 456 +explain select * from t use index (ia) where a != 'aa' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 6656.67 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 6656.67 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 6656.67 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 6656.67 cop[tikv] ne(planner__core__range_scan_for_like.t.a, "aa") + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a != 'aa' order by a,_tidb_rowid; +a b + 234 + 11111 + 66666 + 语 言 3579 + 语言 55555 +A 456 +aab 456 +aabB 456 +aABBccdd 890 +你好 111 +测测试 2468 +测测试 99999 +测试 222 +测试 543 +测试Abc 324 +explain select * from t use index (ia) where a != 'aaBbc' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 6656.67 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 6656.67 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 6656.67 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 6656.67 cop[tikv] ne(planner__core__range_scan_for_like.t.a, "aaBbc") + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a != 'aaBbc' order by a,_tidb_rowid; +a b + 234 + 11111 + 66666 + 语 言 3579 + 语言 55555 +A 456 +Aa 456 +aab 456 +aabB 456 +aABBccdd 890 +你好 111 +测测试 2468 +测测试 99999 +测试 222 +测试 543 +测试Abc 324 +explain select * from t use index (ia) where a like '测试abc' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试abc", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like '测试abc' order by a,_tidb_rowid; +a b +测试Abc 324 +explain select * from t use index (ia) where a = '测试abc' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 10.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 10.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 10.00 root + ├─IndexRangeScan_9(Build) 10.00 cop[tikv] table:t, index:ia(a) range:["测试a","测试a"], keep order:false, stats:pseudo + └─Selection_11(Probe) 10.00 cop[tikv] eq(planner__core__range_scan_for_like.t.a, "测试abc") + └─TableRowIDScan_10 10.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a = '测试abc' order by a,_tidb_rowid; +a b +测试Abc 324 +explain select * from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "aa", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +a b +Aa 456 +explain select * from t use index (ia) where a = 'aa' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 10.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 10.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 10.00 root + ├─IndexRangeScan_9(Build) 10.00 cop[tikv] table:t, index:ia(a) range:["aa","aa"], keep order:false, stats:pseudo + └─Selection_11(Probe) 10.00 cop[tikv] eq(planner__core__range_scan_for_like.t.a, "aa") + └─TableRowIDScan_10 10.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a = 'aa' order by a,_tidb_rowid; +a b +Aa 456 +explain select * from t use index (ia) where a like '测测试 ' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测测试 ", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like '测测试 ' order by a,_tidb_rowid; +a b +测测试 2468 +explain select * from t use index (ia) where a = '测测试 ' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 10.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 10.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 10.00 root + ├─IndexRangeScan_9(Build) 10.00 cop[tikv] table:t, index:ia(a) range:["测测试","测测试"], keep order:false, stats:pseudo + └─Selection_11(Probe) 10.00 cop[tikv] eq(planner__core__range_scan_for_like.t.a, "测测试 ") + └─TableRowIDScan_10 10.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a = '测测试 ' order by a,_tidb_rowid; +a b +测测试 2468 +测测试 99999 +explain select * from t use index (ia) where a like ' 语 言' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " 语 言", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like ' 语 言' order by a,_tidb_rowid; +a b + 语 言 3579 +explain select * from t use index (ia) where a = ' 语 言' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 10.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 10.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 10.00 root + ├─IndexRangeScan_9(Build) 10.00 cop[tikv] table:t, index:ia(a) range:[" 语"," 语"], keep order:false, stats:pseudo + └─Selection_11(Probe) 10.00 cop[tikv] eq(planner__core__range_scan_for_like.t.a, " 语 言") + └─TableRowIDScan_10 10.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a = ' 语 言' order by a,_tidb_rowid; +a b + 语 言 3579 +explain select * from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试%", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +a b +测试 222 +测试 543 +测试Abc 324 +explain select * from t use index (ia) where a like '测_' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测_", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like '测_' order by a,_tidb_rowid; +a b +测试 222 +explain select * from t use index (ia) where a like '测测试 %' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测测试 %", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like '测测试 %' order by a,_tidb_rowid; +a b +测测试 2468 +测测试 99999 +explain select * from t use index (ia) where a like '测试a__' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试a__", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like '测试a__' order by a,_tidb_rowid; +a b +测试Abc 324 +explain select * from t use index (ia) where a like '测试 __' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, "测试 __", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like '测试 __' order by a,_tidb_rowid; +a b +测试 543 +explain select * from t use index (ia) where a like ' _' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " _", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like ' _' order by a,_tidb_rowid; +a b +explain select * from t use index (ia) where a like ' %' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " %", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like ' %' order by a,_tidb_rowid; +a b + 66666 +explain select * from t use index (ia) where a like ' 语言%%' order by a,_tidb_rowid; +id estRows task access object operator info +Projection_6 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t.b +└─Sort_7 8000.00 root planner__core__range_scan_for_like.t.a, planner__core__range_scan_for_like.t._tidb_rowid + └─IndexLookUp_12 8000.00 root + ├─IndexFullScan_9(Build) 10000.00 cop[tikv] table:t, index:ia(a) keep order:false, stats:pseudo + └─Selection_11(Probe) 8000.00 cop[tikv] like(planner__core__range_scan_for_like.t.a, " 语言%%", 92) + └─TableRowIDScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +select * from t use index (ia) where a like ' 语言%%' order by a,_tidb_rowid; +a b + 语言 55555 diff --git a/tests/integrationtest/t/planner/core/range_scan_for_like.test b/tests/integrationtest/t/planner/core/range_scan_for_like.test new file mode 100644 index 0000000000000..c6113bc053bfe --- /dev/null +++ b/tests/integrationtest/t/planner/core/range_scan_for_like.test @@ -0,0 +1,243 @@ +# Suite 1: utf8mb4_general_ci + normal index +create table t(a varchar(20) collate utf8mb4_general_ci, index ia(a)); +insert into t value('测试'),('测试Abc'),('测试 '),('你好'),('aABBccdd'),('Aa'),(''),(' '),(' '),(' 语言'),(' 语 言 '),('测测试 '),('测测试 '),(NULL); +# test cases for the pattern string cover: +# with/without wildcard +# start/end with wildcard +# [non-]ascii characters +# [only] contain empty string/space +explain select *, length(a) from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '测%%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '测%%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '测%%试' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '测%%试' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '测试%%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '测试%%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '测试_' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '测试_' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '你好%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '你好%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa%cc' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa%cc' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like ' ' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like ' ' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa%dd' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa%dd' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa%%dd' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa%%dd' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa_bccdd' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa_bccdd' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '%%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '%%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like ' %%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like ' %%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like ' %%语言' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like ' %%语言' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like ' 语 %' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like ' 语 %' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like ' 语 _' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like ' 语 _' order by a,_tidb_rowid; +drop table t; +# Suite 2: utf8mb4_unicode_ci + unique index +create table t(a varchar(20) collate utf8mb4_unicode_ci, unique index ia(a)); +insert into t value(''),('测试'),('测试abc'),('你好'),('aabbccdd'),(' 语言'),(' 语 言 '),('测测试 '); +# test cases for the pattern string are the same with Suite 1 +explain select *, length(a) from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '测%%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '测%%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '测%%试' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '测%%试' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '测试%%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '测试%%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '测试_' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '测试_' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '你好%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '你好%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa%cc' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa%cc' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa%dd' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa%dd' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa%%dd' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa%%dd' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like 'aa_bccdd' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like 'aa_bccdd' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like '%%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like '%%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like ' %%' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like ' %%' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like ' %%语言' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like ' %%语言' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like ' 语 %' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like ' 语 %' order by a,_tidb_rowid; +explain select *, length(a) from t use index (ia) where a like ' 语 _' order by a,_tidb_rowid; +select *, length(a) from t use index (ia) where a like ' 语 _' order by a,_tidb_rowid; +drop table t; +# Suite 3: utf8mb4_0900_ai_ci + ascii_bin + multi-column index + prefix index + primary key (clustered) +create table t(a varchar(20) collate utf8mb4_0900_ai_ci, b varchar(20) collate ascii_bin, c bigint, primary key(a(1), b) clustered); +insert into t (a, b, c) values +('测试1', 'asdfgh', 345346), +('你好2', 'qqwweerrrr', 987765), +('こんにちは3', 'zxcvbnn', 1111111), +('안녕하세요4', 'asdfgh ', 3333333333), +('Ciao5', ' asdfgh', 444400), +('Hola6', ' asdfgh ', 6666), +('Bonjour ', '', 888888888), +('Olá8', ' ', 9999999), +('Привет9', ' ', 321321), +('Hallo10', '12345', 35678); +explain select * from t use index (primary) where a like '测试%' and b like 'asd%' order by a,b; +select * from t use index (primary) where a like '测试%' and b like 'asd%' order by a,b; +explain select * from t use index (primary) where a like '测试1' and b like 'asdfgh %' order by a,b; +select * from t use index (primary) where a like '测试1' and b like 'asdfgh %' order by a,b; +explain select * from t use index (primary) where a like 'こんにち_' and b like 'zxc%' order by a,b; +select * from t use index (primary) where a like 'こんにち_' and b like 'zxc%' order by a,b; +explain select * from t use index (primary) where a like '안녕하세요%' and b like 'asd%' order by a,b; +select * from t use index (primary) where a like '안녕하세요%' and b like 'asd%' order by a,b; +explain select * from t use index (primary) where a like 'Ciáo%' and b like ' _%' order by a,b; +select * from t use index (primary) where a like 'Ciáo%' and b like ' _%' order by a,b; +explain select * from t use index (primary) where a like '%HoLa%' and b like ' asdfgh' order by a,b; +select * from t use index (primary) where a like '%HoLa%' and b like ' asdfgh' order by a,b; +explain select * from t use index (primary) where a like 'bonjour _%' and b like '' order by a,b; +select * from t use index (primary) where a like 'bonjour _%' and b like '' order by a,b; +explain select * from t use index (primary) where a like 'OLa%' and b like '_' order by a,b; +select * from t use index (primary) where a like 'OLa%' and b like '_' order by a,b; +explain select * from t use index (primary) where a like 'Приве__' and b like ' %' order by a,b; +select * from t use index (primary) where a like 'Приве__' and b like ' %' order by a,b; +explain select * from t use index (primary) where a like 'Hallo%' and b like '123%' order by a,b; +select * from t use index (primary) where a like 'Hallo%' and b like '123%' order by a,b; +drop table t; +# Suite 4: gbk_chinese_ci + latin1_bin + multi-column index + prefix index + primary key (nonclustered) +create table t(a varchar(20) collate gbk_chinese_ci, b varchar(20) collate latin1_bin, c bigint, primary key(a, b(5)) nonclustered); +insert into t (a, b, c) values +('测试1', 'asdfgh', 345346), +('你好2', 'qqwweerrrr', 987765), +('zxcvbnn',0xE38193E38293E381ABE381A1E381AF33, 1111111), +('asdfgh ', 0xEC9588EB8595ED9598EC84B8EC9A9434, 3333333333), +('Ciao5', ' asdfgh', 444400), +(' asdfgh ', 'Hola6', 6666), +('Bonjour ', '', 888888888), +('Olá8', ' ', 9999999), +('Привет9', ' ', 321321), +(' ', '12345', 35678); +set names utf8mb4; +explain select * from t use index (primary) where a like '测试%' and b like 'asd%' order by a,b; +select * from t use index (primary) where a like '测试%' and b like 'asd%' order by a,b; +explain select * from t use index (primary) where a like '测试1' and b like 'asdfgh %' order by a,b; +select * from t use index (primary) where a like '测试1' and b like 'asdfgh %' order by a,b; +set names latin1; +explain select * from t use index (primary) where b like 'こんにち_' and a like 'zxc%' order by a,b; +select * from t use index (primary) where b like 'こんにち_' and a like 'zxc%' order by a,b; +explain select * from t use index (primary) where b like '안녕하세요%' and a like 'asd%' order by a,b; +select * from t use index (primary) where b like '안녕하세요%' and a like 'asd%' order by a,b; +set names utf8mb4; +explain select * from t use index (primary) where a like 'Ciao%' and b like ' _%' order by a,b; +select * from t use index (primary) where a like 'Ciao%' and b like ' _%' order by a,b; +explain select * from t use index (primary) where b like 'HoLa%' and a like ' asdfgh' order by a,b; +select * from t use index (primary) where b like 'HoLa%' and a like ' asdfgh' order by a,b; +explain select * from t use index (primary) where a like 'bonjour _%' and b like '' order by a,b; +select * from t use index (primary) where a like 'bonjour _%' and b like '' order by a,b; +explain select * from t use index (primary) where a like 'OLá' and b like '_' order by a,b; +select * from t use index (primary) where a like 'OLá' and b like '_' order by a,b; +explain select * from t use index (primary) where a like 'Приве__' and b like ' %' order by a,b; +select * from t use index (primary) where a like 'Приве__' and b like ' %' order by a,b; +explain select * from t use index (primary) where a like ' %' and b like '123%' order by a,b; +select * from t use index (primary) where a like ' %' and b like '123%' order by a,b; +drop table t; +# Suite 5: utf8mb4_general_ci + prefix index +create table t(a varchar(20) collate utf8mb4_general_ci, b bigint, index ia(a(3))); +insert into t value +('测试',222), +('测试Abc',324), +('测试 ',543), +('你好',111), +('aABBccdd',890), +('A',456), +('Aa',456), +('aab',456), +('aabB',456), +('',234), +(' ',11111), +(' ',66666), +(' 语言',55555), +(' 语 言',3579), +('测测试 ',2468), +('测测试 ',99999), +(NULL,10); +explain select * from t use index (ia) where a > 'aabb' order by a,_tidb_rowid; +select * from t use index (ia) where a > 'aabb' order by a,_tidb_rowid; +explain select * from t use index (ia) where a > 'aab' order by a,_tidb_rowid; +select * from t use index (ia) where a > 'aab' order by a,_tidb_rowid; +explain select * from t use index (ia) where a > 'aa' order by a,_tidb_rowid; +select * from t use index (ia) where a > 'aa' order by a,_tidb_rowid; +explain select * from t use index (ia) where a < 'aabb' order by a,_tidb_rowid; +select * from t use index (ia) where a < 'aabb' order by a,_tidb_rowid; +explain select * from t use index (ia) where a < 'aab' order by a,_tidb_rowid; +select * from t use index (ia) where a < 'aab' order by a,_tidb_rowid; +explain select * from t use index (ia) where a < 'aa' order by a,_tidb_rowid; +select * from t use index (ia) where a < 'aa' order by a,_tidb_rowid; +explain select * from t use index (ia) where a != 'aa' order by a,_tidb_rowid; +select * from t use index (ia) where a != 'aa' order by a,_tidb_rowid; +explain select * from t use index (ia) where a != 'aaBbc' order by a,_tidb_rowid; +select * from t use index (ia) where a != 'aaBbc' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like '测试abc' order by a,_tidb_rowid; +select * from t use index (ia) where a like '测试abc' order by a,_tidb_rowid; +explain select * from t use index (ia) where a = '测试abc' order by a,_tidb_rowid; +select * from t use index (ia) where a = '测试abc' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +select * from t use index (ia) where a like 'aa' order by a,_tidb_rowid; +explain select * from t use index (ia) where a = 'aa' order by a,_tidb_rowid; +select * from t use index (ia) where a = 'aa' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like '测测试 ' order by a,_tidb_rowid; +select * from t use index (ia) where a like '测测试 ' order by a,_tidb_rowid; +explain select * from t use index (ia) where a = '测测试 ' order by a,_tidb_rowid; +select * from t use index (ia) where a = '测测试 ' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like ' 语 言' order by a,_tidb_rowid; +select * from t use index (ia) where a like ' 语 言' order by a,_tidb_rowid; +explain select * from t use index (ia) where a = ' 语 言' order by a,_tidb_rowid; +select * from t use index (ia) where a = ' 语 言' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +select * from t use index (ia) where a like '测试%' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like '测_' order by a,_tidb_rowid; +select * from t use index (ia) where a like '测_' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like '测测试 %' order by a,_tidb_rowid; +select * from t use index (ia) where a like '测测试 %' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like '测试a__' order by a,_tidb_rowid; +select * from t use index (ia) where a like '测试a__' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like '测试 __' order by a,_tidb_rowid; +select * from t use index (ia) where a like '测试 __' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like ' _' order by a,_tidb_rowid; +select * from t use index (ia) where a like ' _' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like ' %' order by a,_tidb_rowid; +select * from t use index (ia) where a like ' %' order by a,_tidb_rowid; +explain select * from t use index (ia) where a like ' 语言%%' order by a,_tidb_rowid; +select * from t use index (ia) where a like ' 语言%%' order by a,_tidb_rowid; + + + + + + + + + + + + + + + +