Unverified Commit bc267f58 authored by Song Gao's avatar Song Gao Committed by GitHub
Browse files

expression: support push down tikv supported functions (#32193)

ref pingcap/tidb#31846
parent 7ceb7334
Showing with 234 additions and 51 deletions
+234 -51
......@@ -705,11 +705,11 @@ c1 c2 c3 c4 c5
explain select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < 10) and truncate(c1, 1) = 1 order by 1;
id estRows task access object operator info
Sort_5 4433.77 root test.t1.c1
└─Selection_8 4433.77 root eq(truncate(test.t1.c1, 1), 1)
─IndexMerge_12 5542.21 root
├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo
├─IndexRangeScan_10(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo
└─TableRowIDScan_11(Probe) 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo
└─IndexMerge_12 4433.77 root
─IndexRangeScan_8(Build) 3323.33 cop[tikv] table:t1, index:c1(c1) range:[-inf,10), keep order:false, stats:pseudo
├─IndexRangeScan_9(Build) 3323.33 cop[tikv] table:t1, index:c2(c2) range:[-inf,10), keep order:false, stats:pseudo
└─Selection_11(Probe) 4433.77 cop[tikv] eq(truncate(test.t1.c1, 1), 1)
└─TableRowIDScan_10 5542.21 cop[tikv] table:t1 keep order:false, stats:pseudo
select /*+ use_index_merge(t1) */ * from t1 where (c1 < 10 or c2 < 10) and truncate(c1, 1) = 1 order by 1;
c1 c2 c3 c4 c5
1 1 1 1 1
......
......@@ -639,6 +639,7 @@ func (c *repeatFunctionClass) getFunction(ctx sessionctx.Context, args []Express
return nil, errors.Trace(err)
}
sig := &builtinRepeatSig{bf, maxAllowedPacket}
sig.setPbCode(tipb.ScalarFuncSig_Repeat)
return sig, nil
}
......@@ -3447,6 +3448,7 @@ func (c *fromBase64FunctionClass) getFunction(ctx sessionctx.Context, args []Exp
types.SetBinChsClnFlag(bf.tp)
sig := &builtinFromBase64Sig{bf, maxAllowedPacket}
sig.setPbCode(tipb.ScalarFuncSig_FromBase64)
return sig, nil
}
......@@ -3522,6 +3524,7 @@ func (c *toBase64FunctionClass) getFunction(ctx sessionctx.Context, args []Expre
}
sig := &builtinToBase64Sig{bf, maxAllowedPacket}
sig.setPbCode(tipb.ScalarFuncSig_ToBase64)
return sig, nil
}
......
......@@ -1232,6 +1232,101 @@ func TestExprPushDownToTiKV(t *testing.T) {
retType: types.NewFieldType(mysql.TypeDate),
args: []Expression{dateColumn},
},
{
functionName: ast.PI,
retType: types.NewFieldType(mysql.TypeDouble),
args: []Expression{},
},
{
functionName: ast.Round,
retType: types.NewFieldType(mysql.TypeDouble),
args: []Expression{intColumn},
},
{
functionName: ast.Truncate,
retType: types.NewFieldType(mysql.TypeDouble),
args: []Expression{intColumn, intColumn},
},
{
functionName: ast.Bin,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{intColumn},
},
{
functionName: ast.Unhex,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{stringColumn},
},
{
functionName: ast.Locate,
retType: types.NewFieldType(mysql.TypeInt24),
args: []Expression{stringColumn, stringColumn},
},
{
functionName: ast.Ord,
retType: types.NewFieldType(mysql.TypeInt24),
args: []Expression{stringColumn},
},
{
functionName: ast.Lpad,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{stringColumn, intColumn, stringColumn},
},
{
functionName: ast.Rpad,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{stringColumn, intColumn, stringColumn},
},
{
functionName: ast.Trim,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{stringColumn},
},
{
functionName: ast.FromBase64,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{stringColumn},
},
{
functionName: ast.ToBase64,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{stringColumn},
},
{
functionName: ast.MakeSet,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{intColumn, stringColumn},
},
{
functionName: ast.SubstringIndex,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{stringColumn, stringColumn, intColumn},
},
{
functionName: ast.Instr,
retType: types.NewFieldType(mysql.TypeInt24),
args: []Expression{stringColumn, stringColumn},
},
{
functionName: ast.Quote,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{stringColumn},
},
{
functionName: ast.Oct,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{intColumn},
},
{
functionName: ast.FindInSet,
retType: types.NewFieldType(mysql.TypeInt24),
args: []Expression{stringColumn, stringColumn},
},
{
functionName: ast.Repeat,
retType: types.NewFieldType(mysql.TypeString),
args: []Expression{stringColumn, intColumn},
},
}
for _, tc := range testcases {
......
......@@ -952,6 +952,7 @@ func scalarExprSupportedByTiKV(sf *ScalarFunction) bool {
ast.LT, ast.LE, ast.EQ, ast.NE, ast.GE, ast.GT, ast.NullEQ, ast.In, ast.IsNull, ast.Like, ast.IsTruthWithoutNull, ast.IsTruthWithNull, ast.IsFalsity,
// arithmetical functions.
ast.PI, ast.Truncate,
ast.Plus, ast.Minus, ast.Mul, ast.Div, ast.Abs, /*ast.Mod,*/
// math functions.
......@@ -966,7 +967,11 @@ func scalarExprSupportedByTiKV(sf *ScalarFunction) bool {
ast.Case, ast.If, ast.Ifnull, ast.Coalesce,
// string functions.
ast.Length, ast.BitLength, ast.Concat, ast.ConcatWS /*ast.Locate,*/, ast.Replace, ast.ASCII, ast.Hex,
ast.Bin, ast.Unhex, ast.Locate, ast.Ord, ast.Lpad, ast.Rpad,
ast.Trim, ast.FromBase64, ast.ToBase64, /* ast.Upper, ast.Lower, ast.InsertFunc */
ast.MakeSet, ast.SubstringIndex, ast.Instr, ast.Quote, ast.Oct,
ast.FindInSet, ast.Repeat,
ast.Length, ast.BitLength, ast.Concat, ast.ConcatWS, ast.Replace, ast.ASCII, ast.Hex,
ast.Reverse, ast.LTrim, ast.RTrim, ast.Strcmp, ast.Space, ast.Elt, ast.Field,
InternalFuncFromBinary, InternalFuncToBinary, ast.Mid, ast.Substring, ast.Substr, ast.CharLength,
ast.Right, ast.Left,
......@@ -980,7 +985,7 @@ func scalarExprSupportedByTiKV(sf *ScalarFunction) bool {
// date functions.
ast.DateFormat, /* Date */
ast.Hour, ast.Minute, ast.Second, ast.MicroSecond, ast.Month, /* ast.MonthName */
ast.DayName, ast.DayOfMonth, ast.DayOfWeek, ast.DayOfYear, /* ast.Week */
/* ast.DayName */ ast.DayOfMonth, ast.DayOfWeek, ast.DayOfYear, /* ast.Week */
ast.Weekday, ast.WeekOfYear, ast.Year, /* ast.YearWeek */
ast.FromDays, ast.ToDays,
ast.PeriodAdd, ast.PeriodDiff, /*ast.TimestampDiff, ast.DateAdd, ast.FromUnixTime,*/
......@@ -997,11 +1002,10 @@ func scalarExprSupportedByTiKV(sf *ScalarFunction) bool {
ast.UUID:
return true
// A special case: Only push down Round by signature
case ast.Round:
switch sf.Function.PbCode() {
case tipb.ScalarFuncSig_RoundReal, tipb.ScalarFuncSig_RoundInt, tipb.ScalarFuncSig_RoundDec:
case tipb.ScalarFuncSig_RoundReal, tipb.ScalarFuncSig_RoundInt, tipb.ScalarFuncSig_RoundDec,
tipb.ScalarFuncSig_RoundWithFracReal, tipb.ScalarFuncSig_RoundWithFracInt, tipb.ScalarFuncSig_RoundWithFracDec:
return true
}
case ast.Rand:
......
......@@ -3483,36 +3483,33 @@ func TestExprPushdown(t *testing.T) {
// case 1, index scan without double read, some filters can not be pushed to cop task
rows := tk.MustQuery("explain format = 'brief' select col2, col1 from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Rows()
require.Equal(t, "root", fmt.Sprintf("%v", rows[1][2]))
require.Equal(t, "eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), \"4\")", fmt.Sprintf("%v", rows[1][4]))
require.Equal(t, "cop[tikv]", fmt.Sprintf("%v", rows[3][2]))
require.Equal(t, "like(test.t.col2, \"5%\", 92)", fmt.Sprintf("%v", rows[3][4]))
require.Equal(t, "cop[tikv]", fmt.Sprintf("%v", rows[2][2]))
require.Equal(t, "eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), \"4\"), like(test.t.col2, \"5%\", 92)", fmt.Sprintf("%v", rows[2][4]))
tk.MustQuery("select col2, col1 from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("511 411111"))
tk.MustQuery("select count(col2) from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("1"))
// case 2, index scan without double read, none of the filters can be pushed to cop task
rows = tk.MustQuery("explain format = 'brief' select col1, col2 from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Rows()
require.Equal(t, "root", fmt.Sprintf("%v", rows[0][2]))
require.Equal(t, "eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), \"4\"), eq(from_base64(to_base64(substr(test.t.col2, 1, 1))), \"5\")", fmt.Sprintf("%v", rows[0][4]))
require.Equal(t, "cop[tikv]", fmt.Sprintf("%v", rows[1][2]))
require.Equal(t, `eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), "4"), eq(from_base64(to_base64(substr(test.t.col2, 1, 1))), "5")`, fmt.Sprintf("%v", rows[1][4]))
tk.MustQuery("select col1, col2 from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("411111 511"))
tk.MustQuery("select count(col1) from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("1"))
// case 3, index scan with double read, some filters can not be pushed to cop task
rows = tk.MustQuery("explain format = 'brief' select id from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Rows()
require.Equal(t, "root", fmt.Sprintf("%v", rows[1][2]))
require.Equal(t, "eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), \"4\")", fmt.Sprintf("%v", rows[1][4]))
require.Equal(t, "cop[tikv]", fmt.Sprintf("%v", rows[3][2]))
require.Equal(t, "like(test.t.col2, \"5%\", 92)", fmt.Sprintf("%v", rows[3][4]))
require.Equal(t, "cop[tikv]", fmt.Sprintf("%v", rows[2][2]))
require.Equal(t, `eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), "4"), like(test.t.col2, "5%", 92)`, fmt.Sprintf("%v", rows[2][4]))
tk.MustQuery("select id from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("3"))
tk.MustQuery("select count(id) from t use index(key1) where col2 like '5%' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("1"))
// case 4, index scan with double read, none of the filters can be pushed to cop task
rows = tk.MustQuery("explain format = 'brief' select id from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Rows()
require.Equal(t, "root", fmt.Sprintf("%v", rows[1][2]))
require.Equal(t, "eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), \"4\"), eq(from_base64(to_base64(substr(test.t.col2, 1, 1))), \"5\")", fmt.Sprintf("%v", rows[1][4]))
require.Equal(t, "cop[tikv]", fmt.Sprintf("%v", rows[2][2]))
require.Equal(t, `eq(from_base64(to_base64(substr(test.t.col1, 1, 1))), "4"), eq(from_base64(to_base64(substr(test.t.col2, 1, 1))), "5")`, fmt.Sprintf("%v", rows[2][4]))
tk.MustQuery("select id from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("3"))
tk.MustQuery("select count(id) from t use index(key2) where from_base64(to_base64(substr(col2, 1, 1))) = '5' and from_base64(to_base64(substr(col1, 1, 1))) = '4'").Check(testkit.Rows("1"))
}
func TestIssue16973(t *testing.T) {
store, clean := testkit.CreateMockStore(t)
defer clean()
......
......@@ -2521,7 +2521,7 @@ func (s *testIntegrationSerialSuite) TestIssue18984(c *C) {
func (s *testIntegrationSuite) TestScalarFunctionPushDown(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("create table t(id int,c varchar(11),d datetime)")
tk.MustExec("create table t(id int,c varchar(11),d datetime,b double)")
tk.MustExec("insert into t(id,c,d) values (1,'abc','2021-12-12')")
rows := [][]interface{}{
{"TableReader_7", "root", "data:Selection_6"},
......@@ -2582,9 +2582,9 @@ func (s *testIntegrationSuite) TestScalarFunctionPushDown(c *C) {
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where month(d);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "dayname(test.t.d)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where dayname(d);").
CheckAt([]int{0, 3, 6}, rows)
//rows[1][2] = "dayname(test.t.d)"
//tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where dayname(d);").
// CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "dayofmonth(test.t.d)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where dayofmonth(d);").
......@@ -2609,6 +2609,87 @@ func (s *testIntegrationSuite) TestScalarFunctionPushDown(c *C) {
rows[1][2] = "last_day(test.t.d)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where last_day(d);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "gt(4, test.t.id)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where pi() > id;").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "truncate(test.t.id, 0)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where truncate(id,0)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "bin(test.t.id)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where bin(id)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "unhex(test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where unhex(c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "locate(test.t.c, test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where locate(c,c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "ord(test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where ord(c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "lpad(test.t.c, 1, test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where lpad(c,1,c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "rpad(test.t.c, 1, test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where rpad(c,1,c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "trim(test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where trim(c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "from_base64(test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where from_base64(c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "to_base64(test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where to_base64(c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "make_set(1, test.t.c, test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where make_set(1,c,c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "substring_index(test.t.c, test.t.c, 1)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where substring_index(c,c,1)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "instr(test.t.c, test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where instr(c,c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "quote(test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where quote(c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "oct(test.t.id)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where oct(id)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "find_in_set(test.t.c, test.t.c)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where find_in_set(c,c)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "repeat(test.t.c, 2)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where repeat(c,2)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "round(test.t.b)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where round(b)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "round(test.t.b, 2)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where round(b,2)").
CheckAt([]int{0, 3, 6}, rows)
}
func (s *testIntegrationSuite) TestDistinctScalarFunctionPushDown(c *C) {
......
......@@ -2062,12 +2062,12 @@
{
"SQL": "select /*+ use_index_merge(t1) */ 1 from t1 where c1 = 'de' or c2 = '10' and from_base64(to_base64(c1)) = 'ab';",
"Plan": [
"Projection 15.99 root 1->Column#5",
"└─Selection 15.99 root or(eq(test.t1.c1, \"de\"), and(eq(test.t1.c2, \"10\"), eq(from_base64(to_base64(test.t1.c1)), \"ab\")))",
" ─IndexMerge 19.99 root ",
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t1, index:c1(c1) range:[\"de\",\"de\"], keep order:false, stats:pseudo",
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t1, index:c2(c2) range:[\"10\",\"10\"], keep order:false, stats:pseudo",
" └─TableRowIDScan(Probe) 19.99 cop[tikv] table:t1 keep order:false, stats:pseudo"
"Projection 17.99 root 1->Column#5",
"└─IndexMerge 0.04 root ",
" ─IndexRangeScan(Build) 10.00 cop[tikv] table:t1, index:c1(c1) range:[\"de\",\"de\"], keep order:false, stats:pseudo",
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t1, index:c2(c2) range:[\"10\",\"10\"], keep order:false, stats:pseudo",
" └─Selection(Probe) 0.04 cop[tikv] or(eq(test.t1.c1, \"de\"), and(eq(test.t1.c2, \"10\"), eq(from_base64(to_base64(test.t1.c1)), \"ab\")))",
" └─TableRowIDScan 19.99 cop[tikv] table:t1 keep order:false, stats:pseudo"
],
"Res": [
"1"
......@@ -2090,12 +2090,12 @@
{
"SQL": "select /*+ use_index_merge(tt1) */ 1 from tt1 where c1 = 'de' or c2 = '10' and from_base64(to_base64(c3)) = '10';",
"Plan": [
"Projection 15.99 root 1->Column#6",
"└─Selection 15.99 root or(eq(test.tt1.c1, \"de\"), and(eq(test.tt1.c2, \"10\"), eq(from_base64(to_base64(test.tt1.c3)), \"10\")))",
" ─IndexMerge 19.99 root ",
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:tt1, index:idx_0(c1) range:[\"de\",\"de\"], keep order:false, stats:pseudo",
" ─IndexRangeScan(Build) 10.00 cop[tikv] table:tt1, index:idx_1(c2, c3) range:[\"10\",\"10\"], keep order:false, stats:pseudo",
" └─TableRowIDScan(Probe) 19.99 cop[tikv] table:tt1 keep order:false, stats:pseudo"
"Projection 17.99 root 1->Column#6",
"└─IndexMerge 17.99 root ",
" ─IndexRangeScan(Build) 10.00 cop[tikv] table:tt1, index:idx_0(c1) range:[\"de\",\"de\"], keep order:false, stats:pseudo",
" ├─Selection(Build) 8.00 cop[tikv] eq(from_base64(to_base64(test.tt1.c3)), \"10\")",
" │ └─IndexRangeScan 10.00 cop[tikv] table:tt1, index:idx_1(c2, c3) range:[\"10\",\"10\"], keep order:false, stats:pseudo",
" └─TableRowIDScan(Probe) 17.99 cop[tikv] table:tt1 keep order:false, stats:pseudo"
],
"Res": [
"1"
......@@ -2104,12 +2104,13 @@
{
"SQL": "select /*+ use_index_merge( tt2 ) */ 1 from tt2 where tt2.c1 in (-3896405) or tt2.pk in (1, 53330) and to_base64(left(pk, 5));",
"Plan": [
"Projection 2.40 root 1->Column#3",
"└─Selection 2.40 root or(eq(test.tt2.c1, -3896405), and(in(test.tt2.pk, 1, 53330), istrue_with_null(cast(to_base64(left(cast(test.tt2.pk, var_string(20)), 5)), double BINARY))))",
" └─IndexMerge 3.00 root ",
" ├─IndexRangeScan(Build) 1.00 cop[tikv] table:tt2, index:c1(c1) range:[-3896405,-3896405], keep order:false, stats:pseudo",
" ├─TableRangeScan(Build) 2.00 cop[tikv] table:tt2 range:[1,1], [53330,53330], keep order:false, stats:pseudo",
" └─TableRowIDScan(Probe) 3.00 cop[tikv] table:tt2 keep order:false, stats:pseudo"
"Projection 2.60 root 1->Column#3",
"└─IndexMerge 0.00 root ",
" ├─IndexRangeScan(Build) 1.00 cop[tikv] table:tt2, index:c1(c1) range:[-3896405,-3896405], keep order:false, stats:pseudo",
" ├─Selection(Build) 1.60 cop[tikv] istrue_with_null(cast(to_base64(left(cast(test.tt2.pk, var_string(20)), 5)), double BINARY))",
" │ └─TableRangeScan 2.00 cop[tikv] table:tt2 range:[1,1], [53330,53330], keep order:false, stats:pseudo",
" └─Selection(Probe) 0.00 cop[tikv] or(eq(test.tt2.c1, -3896405), and(in(test.tt2.pk, 1, 53330), istrue_with_null(cast(to_base64(left(cast(test.tt2.pk, var_string(20)), 5)), double BINARY))))",
" └─TableRowIDScan 3.00 cop[tikv] table:tt2 keep order:false, stats:pseudo"
],
"Res": [
"1"
......@@ -2132,10 +2133,12 @@
{
"SQL": "select 1 from t1 where c1 = 'de' or c2 = '10' and from_base64(to_base64(c1)) = 'ab';",
"Plan": [
"Projection 8000.00 root 1->Column#5",
"└─Selection 8000.00 root or(eq(test.t1.c1, \"de\"), and(eq(test.t1.c2, \"10\"), eq(from_base64(to_base64(test.t1.c1)), \"ab\")))",
" └─TableReader 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
"Projection 17.99 root 1->Column#5",
"└─IndexMerge 0.04 root ",
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t1, index:c1(c1) range:[\"de\",\"de\"], keep order:false, stats:pseudo",
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t1, index:c2(c2) range:[\"10\",\"10\"], keep order:false, stats:pseudo",
" └─Selection(Probe) 0.04 cop[tikv] or(eq(test.t1.c1, \"de\"), and(eq(test.t1.c2, \"10\"), eq(from_base64(to_base64(test.t1.c1)), \"ab\")))",
" └─TableRowIDScan 19.99 cop[tikv] table:t1 keep order:false, stats:pseudo"
],
"Res": [
"1"
......
......@@ -886,7 +886,7 @@
},
{
"SQL": "select sum(to_base64(e)) from t where c = 1",
"Best": "IndexReader(Index(t.c_d_e)[[1,1]])->Projection->StreamAgg"
"Best": "IndexReader(Index(t.c_d_e)[[1,1]]->StreamAgg)->StreamAgg"
},
{
"SQL": "select (select count(1) k from t s where s.a = t.a having k != 0) from t",
......@@ -894,7 +894,7 @@
},
{
"SQL": "select sum(to_base64(e)) from t group by e,d,c order by c",
"Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])->Projection->StreamAgg->Projection"
"Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->StreamAgg)->StreamAgg->Projection"
},
{
"SQL": "select sum(e+1) from t group by e,d,c order by c",
......@@ -902,7 +902,7 @@
},
{
"SQL": "select sum(to_base64(e)) from t group by e,d,c order by c,e",
"Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]])->Projection->StreamAgg->Sort->Projection"
"Best": "IndexReader(Index(t.c_d_e)[[NULL,+inf]]->StreamAgg)->StreamAgg->Sort->Projection"
},
{
"SQL": "select sum(e+1) from t group by e,d,c order by c,e",
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment