planner: let the planner can select IndexMerge on MVIndex without hint (#40347)
ref pingcap/tidb#40191
This commit is contained in:
@ -515,10 +515,6 @@ func (ds *DataSource) generateIndexMergeJSONMVIndexPath(normalPathCnt int, filte
|
||||
if ds.possibleAccessPaths[idx].IsTablePath() || ds.possibleAccessPaths[idx].Index == nil || !ds.possibleAccessPaths[idx].Index.MVIndex {
|
||||
continue // not a MVIndex path
|
||||
}
|
||||
if !ds.isSpecifiedInIndexMergeHints(ds.possibleAccessPaths[idx].Index.Name.L) {
|
||||
continue // for safety, only consider using MVIndex when there is a `use_index_merge` hint now.
|
||||
// TODO: remove this limitation
|
||||
}
|
||||
|
||||
// Step 1. Extract the underlying JSON column from MVIndex Info.
|
||||
mvIndex := ds.possibleAccessPaths[idx].Index
|
||||
@ -635,6 +631,20 @@ func (ds *DataSource) generateIndexMergeJSONMVIndexPath(normalPathCnt int, filte
|
||||
}
|
||||
indexMergePath := ds.buildIndexMergeOrPath(filters, partialPaths, filterIdx)
|
||||
indexMergePath.IndexMergeIsIntersection = indexMergeIsIntersection
|
||||
|
||||
// Step 2.4. Update the estimated rows.
|
||||
// TODO: use a naive estimation strategy here now for simplicity, make it more accurate.
|
||||
minEstRows, maxEstRows := math.MaxFloat64, -1.0
|
||||
for _, p := range indexMergePath.PartialIndexPaths {
|
||||
minEstRows = math.Min(minEstRows, p.CountAfterAccess)
|
||||
maxEstRows = math.Max(maxEstRows, p.CountAfterAccess)
|
||||
}
|
||||
if indexMergePath.IndexMergeIsIntersection {
|
||||
indexMergePath.CountAfterAccess = minEstRows
|
||||
} else {
|
||||
indexMergePath.CountAfterAccess = maxEstRows
|
||||
}
|
||||
|
||||
mvIndexPaths = append(mvIndexPaths, indexMergePath)
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,3 +51,30 @@ index j1((cast(j1 as signed array))))`)
|
||||
result.Check(testkit.Rows(output[i].Plan...))
|
||||
}
|
||||
}
|
||||
|
||||
func TestMVIndexSelection(t *testing.T) {
|
||||
store := testkit.CreateMockStore(t)
|
||||
tk := testkit.NewTestKit(t, store)
|
||||
tk.MustExec("use test")
|
||||
tk.MustExec(`create table t(a int, j json,
|
||||
index i_int((cast(j->'$.int' as signed array))))`)
|
||||
|
||||
var input []string
|
||||
var output []struct {
|
||||
SQL string
|
||||
Plan []string
|
||||
}
|
||||
planSuiteData := core.GetIndexMergeSuiteData()
|
||||
planSuiteData.LoadTestCases(t, &input, &output)
|
||||
|
||||
for i, query := range input {
|
||||
testdata.OnRecord(func() {
|
||||
output[i].SQL = query
|
||||
})
|
||||
result := tk.MustQuery("explain format = 'brief' " + query)
|
||||
testdata.OnRecord(func() {
|
||||
output[i].Plan = testdata.ConvertRowsToStrings(result.Rows())
|
||||
})
|
||||
result.Check(testkit.Rows(output[i].Plan...))
|
||||
}
|
||||
}
|
||||
|
||||
14
planner/core/testdata/index_merge_suite_in.json
vendored
14
planner/core/testdata/index_merge_suite_in.json
vendored
@ -21,6 +21,20 @@
|
||||
"select /*+ use_index_merge(t, j0_0) */ * from t where json_overlaps('1', (j0->'$.path0')) and a<10"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TestMVIndexSelection",
|
||||
"cases": [
|
||||
"select (j->'$.int') from t where (1 member of (j->'$.int'))",
|
||||
"select * from t where (1 member of (j->'$.int'))",
|
||||
"select * from t where (1 member of (j->'$.int')) and a<10",
|
||||
"select (j->'$.int') from t where json_contains((j->'$.int'), '[1, 2, 3]')",
|
||||
"select * from t where json_contains((j->'$.int'), '[1, 2, 3]')",
|
||||
"select * from t where json_contains((j->'$.int'), '[1, 2, 3]') and a<10",
|
||||
"select (j->'$.int') from t where json_overlaps((j->'$.int'), '[1, 2, 3]')",
|
||||
"select * from t where json_overlaps((j->'$.int'), '[1, 2, 3]')",
|
||||
"select * from t where json_overlaps((j->'$.int'), '[1, 2, 3]') and a<10"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TestIndexMergePathGeneration",
|
||||
"cases": [
|
||||
|
||||
209
planner/core/testdata/index_merge_suite_out.json
vendored
209
planner/core/testdata/index_merge_suite_out.json
vendored
@ -5,20 +5,20 @@
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where (1 member of (j0->'$.path0'))",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_memberof(cast(1, json BINARY), json_extract(test.t.j0, \"$.path0\"))",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
"Selection 8.00 root json_memberof(cast(1, json BINARY), json_extract(test.t.j0, \"$.path0\"))",
|
||||
"└─IndexMerge 10.00 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" └─TableRowIDScan(Probe) 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
" └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_1) */ * from t where (1 member of (j0->'$.path1')) and a<10",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_memberof(cast(1, json BINARY), json_extract(test.t.j0, \"$.path1\"))",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
"Selection 8.00 root json_memberof(cast(1, json BINARY), json_extract(test.t.j0, \"$.path1\"))",
|
||||
"└─IndexMerge 3.32 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_1(cast(json_extract(`j0`, _utf8mb4'$.path1') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" └─Selection(Probe) 0.00 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
" └─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -33,143 +33,244 @@
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_1) */ * from t where (1 member of (j0->'$.path1')) and (2 member of (j1)) and a<10",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_memberof(cast(1, json BINARY), json_extract(test.t.j0, \"$.path1\")), json_memberof(cast(2, json BINARY), test.t.j1)",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
"Selection 8.00 root json_memberof(cast(1, json BINARY), json_extract(test.t.j0, \"$.path1\")), json_memberof(cast(2, json BINARY), test.t.j1)",
|
||||
"└─IndexMerge 3.32 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_1(cast(json_extract(`j0`, _utf8mb4'$.path1') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" └─Selection(Probe) 0.00 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
" └─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j1) */ * from t where (1 member of (j0->'$.path1')) and (2 member of (j1)) and a<10",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_memberof(cast(1, json BINARY), json_extract(test.t.j0, \"$.path1\")), json_memberof(cast(2, json BINARY), test.t.j1)",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j1(cast(`j1` as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
" └─Selection(Probe) 0.00 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
"Selection 8.00 root json_memberof(cast(1, json BINARY), json_extract(test.t.j0, \"$.path1\")), json_memberof(cast(2, json BINARY), test.t.j1)",
|
||||
"└─IndexMerge 3.32 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_1(cast(json_extract(`j0`, _utf8mb4'$.path1') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" └─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_contains((j0->'$.path0'), '[1, 2, 3]')",
|
||||
"Plan": [
|
||||
"IndexMerge 0.00 root type: intersection",
|
||||
"IndexMerge 10.00 root type: intersection",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
"└─TableRowIDScan(Probe) 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
"└─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_overlaps((j0->'$.path0'), '[1, 2, 3]')",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_overlaps(json_extract(test.t.j0, \"$.path0\"), cast(\"[1, 2, 3]\", json BINARY))",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
"Selection 8.00 root json_overlaps(json_extract(test.t.j0, \"$.path0\"), cast(\"[1, 2, 3]\", json BINARY))",
|
||||
"└─IndexMerge 10.00 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
" └─TableRowIDScan(Probe) 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
" └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_overlaps('[1, 2, 3]', (j0->'$.path0'))",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_overlaps(cast(\"[1, 2, 3]\", json BINARY), json_extract(test.t.j0, \"$.path0\"))",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
"Selection 8.00 root json_overlaps(cast(\"[1, 2, 3]\", json BINARY), json_extract(test.t.j0, \"$.path0\"))",
|
||||
"└─IndexMerge 10.00 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
" └─TableRowIDScan(Probe) 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
" └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_contains((j0->'$.path0'), '[1, 2, 3]') and a<10",
|
||||
"Plan": [
|
||||
"IndexMerge 0.00 root type: intersection",
|
||||
"IndexMerge 3.32 root type: intersection",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
"└─Selection(Probe) 0.00 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
"└─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_overlaps((j0->'$.path0'), '[1, 2, 3]') and a<10",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_overlaps(json_extract(test.t.j0, \"$.path0\"), cast(\"[1, 2, 3]\", json BINARY))",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
"Selection 8.00 root json_overlaps(json_extract(test.t.j0, \"$.path0\"), cast(\"[1, 2, 3]\", json BINARY))",
|
||||
"└─IndexMerge 3.32 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
" └─Selection(Probe) 0.00 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
" └─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_overlaps('[1, 2, 3]', (j0->'$.path0')) and a<10",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_overlaps(cast(\"[1, 2, 3]\", json BINARY), json_extract(test.t.j0, \"$.path0\"))",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
"Selection 8.00 root json_overlaps(cast(\"[1, 2, 3]\", json BINARY), json_extract(test.t.j0, \"$.path0\"))",
|
||||
"└─IndexMerge 3.32 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
" └─Selection(Probe) 0.00 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
" └─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_contains((j0->'$.path0'), '1')",
|
||||
"Plan": [
|
||||
"IndexMerge 0.00 root type: intersection",
|
||||
"IndexMerge 10.00 root type: intersection",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
"└─TableRowIDScan(Probe) 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
"└─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_overlaps((j0->'$.path0'), '1')",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_overlaps(json_extract(test.t.j0, \"$.path0\"), cast(\"1\", json BINARY))",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
"Selection 8.00 root json_overlaps(json_extract(test.t.j0, \"$.path0\"), cast(\"1\", json BINARY))",
|
||||
"└─IndexMerge 10.00 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" └─TableRowIDScan(Probe) 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
" └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_overlaps('1', (j0->'$.path0'))",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_overlaps(cast(\"1\", json BINARY), json_extract(test.t.j0, \"$.path0\"))",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
"Selection 8.00 root json_overlaps(cast(\"1\", json BINARY), json_extract(test.t.j0, \"$.path0\"))",
|
||||
"└─IndexMerge 10.00 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" └─TableRowIDScan(Probe) 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
" └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_contains((j0->'$.path0'), '1') and a<10",
|
||||
"Plan": [
|
||||
"IndexMerge 0.00 root type: intersection",
|
||||
"IndexMerge 3.32 root type: intersection",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
"└─Selection(Probe) 0.00 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
"└─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_overlaps((j0->'$.path0'), '1') and a<10",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_overlaps(json_extract(test.t.j0, \"$.path0\"), cast(\"1\", json BINARY))",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
"Selection 8.00 root json_overlaps(json_extract(test.t.j0, \"$.path0\"), cast(\"1\", json BINARY))",
|
||||
"└─IndexMerge 3.32 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" └─Selection(Probe) 0.00 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
" └─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ use_index_merge(t, j0_0) */ * from t where json_overlaps('1', (j0->'$.path0')) and a<10",
|
||||
"Plan": [
|
||||
"Selection 0.00 root json_overlaps(cast(\"1\", json BINARY), json_extract(test.t.j0, \"$.path0\"))",
|
||||
"└─IndexMerge 0.00 root type: union",
|
||||
"Selection 8.00 root json_overlaps(cast(\"1\", json BINARY), json_extract(test.t.j0, \"$.path0\"))",
|
||||
"└─IndexMerge 3.32 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:j0_0(cast(json_extract(`j0`, _utf8mb4'$.path0') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" └─Selection(Probe) 0.00 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 0.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
" └─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "TestMVIndexSelection",
|
||||
"Cases": [
|
||||
{
|
||||
"SQL": "select (j->'$.int') from t where (1 member of (j->'$.int'))",
|
||||
"Plan": [
|
||||
"Projection 8000.00 root json_extract(test.t.j, $.int)->Column#5",
|
||||
"└─Selection 8000.00 root json_memberof(cast(1, json BINARY), json_extract(test.t.j, \"$.int\"))",
|
||||
" └─IndexMerge 10.00 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select * from t where (1 member of (j->'$.int'))",
|
||||
"Plan": [
|
||||
"Selection 8000.00 root json_memberof(cast(1, json BINARY), json_extract(test.t.j, \"$.int\"))",
|
||||
"└─IndexMerge 10.00 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select * from t where (1 member of (j->'$.int')) and a<10",
|
||||
"Plan": [
|
||||
"Selection 2658.67 root json_memberof(cast(1, json BINARY), json_extract(test.t.j, \"$.int\"))",
|
||||
"└─IndexMerge 3.32 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" └─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select (j->'$.int') from t where json_contains((j->'$.int'), '[1, 2, 3]')",
|
||||
"Plan": [
|
||||
"Projection 8000.00 root json_extract(test.t.j, $.int)->Column#5",
|
||||
"└─IndexMerge 10.00 root type: intersection",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
" └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select * from t where json_contains((j->'$.int'), '[1, 2, 3]')",
|
||||
"Plan": [
|
||||
"IndexMerge 10.00 root type: intersection",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
"└─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select * from t where json_contains((j->'$.int'), '[1, 2, 3]') and a<10",
|
||||
"Plan": [
|
||||
"IndexMerge 3.32 root type: intersection",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
"└─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select (j->'$.int') from t where json_overlaps((j->'$.int'), '[1, 2, 3]')",
|
||||
"Plan": [
|
||||
"Projection 8000.00 root json_extract(test.t.j, $.int)->Column#5",
|
||||
"└─Selection 8000.00 root json_overlaps(json_extract(test.t.j, \"$.int\"), cast(\"[1, 2, 3]\", json BINARY))",
|
||||
" └─IndexMerge 10.00 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
" └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select * from t where json_overlaps((j->'$.int'), '[1, 2, 3]')",
|
||||
"Plan": [
|
||||
"Selection 8000.00 root json_overlaps(json_extract(test.t.j, \"$.int\"), cast(\"[1, 2, 3]\", json BINARY))",
|
||||
"└─IndexMerge 10.00 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
" └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"SQL": "select * from t where json_overlaps((j->'$.int'), '[1, 2, 3]') and a<10",
|
||||
"Plan": [
|
||||
"Selection 2658.67 root json_overlaps(json_extract(test.t.j, \"$.int\"), cast(\"[1, 2, 3]\", json BINARY))",
|
||||
"└─IndexMerge 3.32 root type: union",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[1,1], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[2,2], keep order:false, stats:pseudo",
|
||||
" ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:i_int(cast(json_extract(`j`, _utf8mb4'$.int') as signed array)) range:[3,3], keep order:false, stats:pseudo",
|
||||
" └─Selection(Probe) 3.32 cop[tikv] lt(test.t.a, 10)",
|
||||
" └─TableRowIDScan 10.00 cop[tikv] table:t keep order:false, stats:pseudo"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user