mirror of https://github.com/mongodb/mongo
SERVER-113717 Enumerate INLJ plans in bottom-up enumerator (#44869)
GitOrigin-RevId: ee2d00b5184756d618c1732423367abcd0edfbed
This commit is contained in:
parent
55a2afb898
commit
1e14d732b9
|
|
@ -816,6 +816,113 @@ Execution Engine: sbe
|
|||
```
|
||||
usedJoinOptimization: true
|
||||
|
||||
### With bottom-up plan enumeration and indexes
|
||||
### Pipeline
|
||||
```json
|
||||
[
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign1",
|
||||
"as" : "x",
|
||||
"localField" : "a",
|
||||
"foreignField" : "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$x"
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign2",
|
||||
"as" : "y",
|
||||
"localField" : "b",
|
||||
"foreignField" : "b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$y"
|
||||
}
|
||||
]
|
||||
```
|
||||
### Results
|
||||
```json
|
||||
{ "_id" : 1, "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "_id" : 1, "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
{ "_id" : 2, "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "_id" : 2, "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
{ "_id" : 2, "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 } }
|
||||
{ "_id" : 2, "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 } }
|
||||
```
|
||||
### Summarized explain
|
||||
Execution Engine: sbe
|
||||
```json
|
||||
{
|
||||
"queryShapeHash" : "2312073BEBB7A5E1754E2D03D9CB40B75C126DBF60867D4639E7E281C9E3DFAC",
|
||||
"rejectedPlans" : [ ],
|
||||
"winningPlan" : {
|
||||
"inputStages" : [
|
||||
{
|
||||
"inputStages" : [
|
||||
{
|
||||
"direction" : "forward",
|
||||
"filter" : {
|
||||
|
||||
},
|
||||
"nss" : "test.basic_joins_md",
|
||||
"stage" : "COLLSCAN"
|
||||
},
|
||||
{
|
||||
"inputStage" : {
|
||||
"indexName" : "a_1",
|
||||
"isMultiKey" : false,
|
||||
"isPartial" : false,
|
||||
"isSparse" : false,
|
||||
"isUnique" : false,
|
||||
"keyPattern" : {
|
||||
"a" : 1
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign1",
|
||||
"stage" : "INDEX_PROBE_NODE"
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign1",
|
||||
"stage" : "FETCH"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"a = a"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"rightEmbeddingField" : "x",
|
||||
"stage" : "INDEXED_NESTED_LOOP_JOIN_EMBEDDING"
|
||||
},
|
||||
{
|
||||
"inputStage" : {
|
||||
"indexName" : "b_1",
|
||||
"isMultiKey" : false,
|
||||
"isPartial" : false,
|
||||
"isSparse" : false,
|
||||
"isUnique" : false,
|
||||
"keyPattern" : {
|
||||
"b" : 1
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign2",
|
||||
"stage" : "INDEX_PROBE_NODE"
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign2",
|
||||
"stage" : "FETCH"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"b = b"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"planNodeId" : 7,
|
||||
"rightEmbeddingField" : "y",
|
||||
"stage" : "INDEXED_NESTED_LOOP_JOIN_EMBEDDING"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Basic example with two joins and suffix
|
||||
### No join opt
|
||||
### Pipeline
|
||||
|
|
@ -1891,6 +1998,143 @@ Execution Engine: sbe
|
|||
```
|
||||
usedJoinOptimization: true
|
||||
|
||||
### With bottom-up plan enumeration and indexes
|
||||
### Pipeline
|
||||
```json
|
||||
[
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign1",
|
||||
"as" : "x",
|
||||
"localField" : "a",
|
||||
"foreignField" : "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$x"
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign2",
|
||||
"as" : "y",
|
||||
"localField" : "b",
|
||||
"foreignField" : "b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$y"
|
||||
},
|
||||
{
|
||||
"$sortByCount" : "$y.b"
|
||||
}
|
||||
]
|
||||
```
|
||||
### Results
|
||||
```json
|
||||
{ "_id" : "bar", "count" : 6 }
|
||||
```
|
||||
### Summarized explain
|
||||
Execution Engine: sbe
|
||||
```json
|
||||
{
|
||||
"queryShapeHash" : "8E0DF14D3DA69D8B1CF0361E869369F9C5E5F2F2A5D81998E6800BDA4F997B57",
|
||||
"stages" : [
|
||||
{
|
||||
"$cursor" : {
|
||||
"rejectedPlans" : [ ],
|
||||
"winningPlan" : {
|
||||
"inputStages" : [
|
||||
{
|
||||
"inputStages" : [
|
||||
{
|
||||
"inputStage" : {
|
||||
"direction" : "forward",
|
||||
"filter" : {
|
||||
|
||||
},
|
||||
"nss" : "test.basic_joins_md",
|
||||
"stage" : "COLLSCAN"
|
||||
},
|
||||
"stage" : "PROJECTION_SIMPLE",
|
||||
"transformBy" : {
|
||||
"_id" : false,
|
||||
"a" : true,
|
||||
"b" : true
|
||||
}
|
||||
},
|
||||
{
|
||||
"inputStage" : {
|
||||
"indexName" : "a_1",
|
||||
"isMultiKey" : false,
|
||||
"isPartial" : false,
|
||||
"isSparse" : false,
|
||||
"isUnique" : false,
|
||||
"keyPattern" : {
|
||||
"a" : 1
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign1",
|
||||
"stage" : "INDEX_PROBE_NODE"
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign1",
|
||||
"stage" : "FETCH"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"a = a"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"rightEmbeddingField" : "x",
|
||||
"stage" : "INDEXED_NESTED_LOOP_JOIN_EMBEDDING"
|
||||
},
|
||||
{
|
||||
"inputStage" : {
|
||||
"indexName" : "b_1",
|
||||
"isMultiKey" : false,
|
||||
"isPartial" : false,
|
||||
"isSparse" : false,
|
||||
"isUnique" : false,
|
||||
"keyPattern" : {
|
||||
"b" : 1
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign2",
|
||||
"stage" : "INDEX_PROBE_NODE"
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign2",
|
||||
"stage" : "FETCH"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"b = b"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"planNodeId" : 8,
|
||||
"rightEmbeddingField" : "y",
|
||||
"stage" : "INDEXED_NESTED_LOOP_JOIN_EMBEDDING"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"$group" : {
|
||||
"$willBeMerged" : false,
|
||||
"_id" : "$y.b",
|
||||
"count" : {
|
||||
"$sum" : {
|
||||
"$const" : 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"$sort" : {
|
||||
"sortKey" : {
|
||||
"count" : -1
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 3. Basic example with referencing field from previous lookup
|
||||
### No join opt
|
||||
### Pipeline
|
||||
|
|
@ -2683,6 +2927,103 @@ Execution Engine: sbe
|
|||
```
|
||||
usedJoinOptimization: true
|
||||
|
||||
### With bottom-up plan enumeration and indexes
|
||||
### Pipeline
|
||||
```json
|
||||
[
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign1",
|
||||
"as" : "x",
|
||||
"localField" : "a",
|
||||
"foreignField" : "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$x"
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign3",
|
||||
"as" : "z",
|
||||
"localField" : "x.c",
|
||||
"foreignField" : "c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$z"
|
||||
}
|
||||
]
|
||||
```
|
||||
### Results
|
||||
```json
|
||||
{ "_id" : 0, "a" : 1, "b" : "foo", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "z" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 } }
|
||||
{ "_id" : 1, "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "z" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 } }
|
||||
{ "_id" : 2, "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "z" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 } }
|
||||
{ "_id" : 2, "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "z" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 } }
|
||||
```
|
||||
### Summarized explain
|
||||
Execution Engine: sbe
|
||||
```json
|
||||
{
|
||||
"queryShapeHash" : "DC5CAF413E9B6B8B5E8B2D3FB91E4D546524BF2707BBE30472D5CA8E12F6637E",
|
||||
"rejectedPlans" : [ ],
|
||||
"winningPlan" : {
|
||||
"inputStages" : [
|
||||
{
|
||||
"inputStages" : [
|
||||
{
|
||||
"direction" : "forward",
|
||||
"filter" : {
|
||||
|
||||
},
|
||||
"nss" : "test.basic_joins_md",
|
||||
"stage" : "COLLSCAN"
|
||||
},
|
||||
{
|
||||
"inputStage" : {
|
||||
"indexName" : "a_1",
|
||||
"isMultiKey" : false,
|
||||
"isPartial" : false,
|
||||
"isSparse" : false,
|
||||
"isUnique" : false,
|
||||
"keyPattern" : {
|
||||
"a" : 1
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign1",
|
||||
"stage" : "INDEX_PROBE_NODE"
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign1",
|
||||
"stage" : "FETCH"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"a = a"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"rightEmbeddingField" : "x",
|
||||
"stage" : "INDEXED_NESTED_LOOP_JOIN_EMBEDDING"
|
||||
},
|
||||
{
|
||||
"direction" : "forward",
|
||||
"filter" : {
|
||||
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign3",
|
||||
"stage" : "COLLSCAN"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"x.c = c"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"planNodeId" : 6,
|
||||
"rightEmbeddingField" : "z",
|
||||
"stage" : "HASH_JOIN_EMBEDDING"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Basic example with 3 joins & subsequent join referencing fields from previous lookups
|
||||
### No join opt
|
||||
### Pipeline
|
||||
|
|
@ -3753,6 +4094,142 @@ Execution Engine: sbe
|
|||
```
|
||||
usedJoinOptimization: true
|
||||
|
||||
### With bottom-up plan enumeration and indexes
|
||||
### Pipeline
|
||||
```json
|
||||
[
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign1",
|
||||
"as" : "x",
|
||||
"localField" : "a",
|
||||
"foreignField" : "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$x"
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign2",
|
||||
"as" : "y",
|
||||
"localField" : "b",
|
||||
"foreignField" : "b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$y"
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign3",
|
||||
"as" : "z",
|
||||
"localField" : "x.c",
|
||||
"foreignField" : "c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$z"
|
||||
}
|
||||
]
|
||||
```
|
||||
### Results
|
||||
```json
|
||||
{ "_id" : 1, "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 }, "z" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 } }
|
||||
{ "_id" : 1, "a" : 1, "b" : "bar", "x" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 }, "z" : { "_id" : 0, "a" : 1, "c" : "zoo", "d" : 1 } }
|
||||
{ "_id" : 2, "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 }, "z" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 } }
|
||||
{ "_id" : 2, "a" : 2, "b" : "bar", "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 }, "z" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 } }
|
||||
{ "_id" : 2, "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 0, "b" : "bar", "d" : 2 }, "z" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 } }
|
||||
{ "_id" : 2, "a" : 2, "b" : "bar", "x" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 }, "y" : { "_id" : 1, "b" : "bar", "d" : 6 }, "z" : { "_id" : 2, "a" : 2, "c" : "x", "d" : 3 } }
|
||||
```
|
||||
### Summarized explain
|
||||
Execution Engine: sbe
|
||||
```json
|
||||
{
|
||||
"queryShapeHash" : "DD24FFAE1F16C6C1F5B03939E0C642A797120A2585058C72554C9649BEA427AB",
|
||||
"rejectedPlans" : [ ],
|
||||
"winningPlan" : {
|
||||
"inputStages" : [
|
||||
{
|
||||
"inputStages" : [
|
||||
{
|
||||
"inputStages" : [
|
||||
{
|
||||
"direction" : "forward",
|
||||
"filter" : {
|
||||
|
||||
},
|
||||
"nss" : "test.basic_joins_md",
|
||||
"stage" : "COLLSCAN"
|
||||
},
|
||||
{
|
||||
"inputStage" : {
|
||||
"indexName" : "a_1",
|
||||
"isMultiKey" : false,
|
||||
"isPartial" : false,
|
||||
"isSparse" : false,
|
||||
"isUnique" : false,
|
||||
"keyPattern" : {
|
||||
"a" : 1
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign1",
|
||||
"stage" : "INDEX_PROBE_NODE"
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign1",
|
||||
"stage" : "FETCH"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"a = a"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"rightEmbeddingField" : "x",
|
||||
"stage" : "INDEXED_NESTED_LOOP_JOIN_EMBEDDING"
|
||||
},
|
||||
{
|
||||
"inputStage" : {
|
||||
"indexName" : "b_1",
|
||||
"isMultiKey" : false,
|
||||
"isPartial" : false,
|
||||
"isSparse" : false,
|
||||
"isUnique" : false,
|
||||
"keyPattern" : {
|
||||
"b" : 1
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign2",
|
||||
"stage" : "INDEX_PROBE_NODE"
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign2",
|
||||
"stage" : "FETCH"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"b = b"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"rightEmbeddingField" : "y",
|
||||
"stage" : "INDEXED_NESTED_LOOP_JOIN_EMBEDDING"
|
||||
},
|
||||
{
|
||||
"direction" : "forward",
|
||||
"filter" : {
|
||||
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign3",
|
||||
"stage" : "COLLSCAN"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"x.c = c"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"planNodeId" : 9,
|
||||
"rightEmbeddingField" : "z",
|
||||
"stage" : "HASH_JOIN_EMBEDDING"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 5. Basic example with 3 joins & subsequent join referencing nested paths
|
||||
### No join opt
|
||||
### Pipeline
|
||||
|
|
@ -4770,3 +5247,126 @@ Execution Engine: sbe
|
|||
```
|
||||
usedJoinOptimization: true
|
||||
|
||||
### With bottom-up plan enumeration and indexes
|
||||
### Pipeline
|
||||
```json
|
||||
[
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign1",
|
||||
"as" : "x",
|
||||
"localField" : "a",
|
||||
"foreignField" : "a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$x"
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign3",
|
||||
"as" : "w.y",
|
||||
"localField" : "x.c",
|
||||
"foreignField" : "c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$w.y"
|
||||
},
|
||||
{
|
||||
"$lookup" : {
|
||||
"from" : "basic_joins_md_foreign2",
|
||||
"as" : "k.y.z",
|
||||
"localField" : "w.y.d",
|
||||
"foreignField" : "d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$unwind" : "$k.y.z"
|
||||
}
|
||||
]
|
||||
```
|
||||
### Results
|
||||
```json
|
||||
{ "_id" : 2, "a" : 2, "b" : "bar", "k" : { "y" : { "z" : { "_id" : 0, "b" : "bar", "d" : 2 } } }, "w" : { "y" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 } }, "x" : { "_id" : 1, "a" : 2, "c" : "blah", "d" : 2 } }
|
||||
```
|
||||
### Summarized explain
|
||||
Execution Engine: sbe
|
||||
```json
|
||||
{
|
||||
"queryShapeHash" : "9226A4FAA10C8790B27D9B5B865D46D0C58179A837F014E6289A34A6EBE76420",
|
||||
"rejectedPlans" : [ ],
|
||||
"winningPlan" : {
|
||||
"inputStages" : [
|
||||
{
|
||||
"inputStages" : [
|
||||
{
|
||||
"inputStages" : [
|
||||
{
|
||||
"direction" : "forward",
|
||||
"filter" : {
|
||||
|
||||
},
|
||||
"nss" : "test.basic_joins_md",
|
||||
"stage" : "COLLSCAN"
|
||||
},
|
||||
{
|
||||
"inputStage" : {
|
||||
"indexName" : "a_1",
|
||||
"isMultiKey" : false,
|
||||
"isPartial" : false,
|
||||
"isSparse" : false,
|
||||
"isUnique" : false,
|
||||
"keyPattern" : {
|
||||
"a" : 1
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign1",
|
||||
"stage" : "INDEX_PROBE_NODE"
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign1",
|
||||
"stage" : "FETCH"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"a = a"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"rightEmbeddingField" : "x",
|
||||
"stage" : "INDEXED_NESTED_LOOP_JOIN_EMBEDDING"
|
||||
},
|
||||
{
|
||||
"direction" : "forward",
|
||||
"filter" : {
|
||||
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign3",
|
||||
"stage" : "COLLSCAN"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"x.c = c"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"rightEmbeddingField" : "w.y",
|
||||
"stage" : "HASH_JOIN_EMBEDDING"
|
||||
},
|
||||
{
|
||||
"direction" : "forward",
|
||||
"filter" : {
|
||||
|
||||
},
|
||||
"nss" : "test.basic_joins_md_foreign2",
|
||||
"stage" : "COLLSCAN"
|
||||
}
|
||||
],
|
||||
"joinPredicates" : [
|
||||
"w.y.d = d"
|
||||
],
|
||||
"leftEmbeddingField" : "none",
|
||||
"planNodeId" : 8,
|
||||
"rightEmbeddingField" : "k.y.z",
|
||||
"stage" : "HASH_JOIN_EMBEDDING"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -139,21 +139,41 @@ function runBasicJoinTest(pipeline) {
|
|||
outputAggregationPlanAndResults(coll, pipeline, {}, true, false, true /* noLineBreak*/);
|
||||
const seed420HJResults = coll.aggregate(pipeline).toArray();
|
||||
verifyExplainOutput(pipeline, true /* joinOptExpectedInExplainOutput */);
|
||||
assert(
|
||||
_resultSetsEqualUnordered(noJoinOptResults, seed420HJResults),
|
||||
"Results differ between no join opt and seed 420 HJ",
|
||||
);
|
||||
|
||||
assert.commandWorked(db.adminCommand({setParameter: 1, internalRandomJoinReorderDefaultToHashJoin: false}));
|
||||
|
||||
foreignColl1.createIndex({a: 1});
|
||||
foreignColl2.createIndex({b: 1});
|
||||
subSection("With fixed order, index join");
|
||||
|
||||
outputAggregationPlanAndResults(coll, pipeline, {}, true, false, true /* noLineBreak*/);
|
||||
const seedINJResults = coll.aggregate(pipeline).toArray();
|
||||
verifyExplainOutput(pipeline, true /* joinOptExpectedInExplainOutput */);
|
||||
const seedINLJResults = coll.aggregate(pipeline).toArray();
|
||||
assert(
|
||||
_resultSetsEqualUnordered(noJoinOptResults, seedINLJResults),
|
||||
"Results differ between no join opt and INLJ",
|
||||
);
|
||||
|
||||
subSection("With bottom-up plan enumeration and indexes");
|
||||
assert.commandWorked(
|
||||
db.adminCommand({
|
||||
setParameter: 1,
|
||||
internalJoinReorderMode: "bottomUp",
|
||||
internalJoinPlanTreeShape: "leftDeep",
|
||||
}),
|
||||
);
|
||||
outputAggregationPlanAndResults(coll, pipeline, {}, true, false);
|
||||
const bottomUpINLJResults = coll.aggregate(pipeline).toArray();
|
||||
assert(
|
||||
_resultSetsEqualUnordered(noJoinOptResults, bottomUpINLJResults),
|
||||
"Results differ between no join opt and INLJ",
|
||||
);
|
||||
|
||||
foreignColl1.dropIndex({a: 1});
|
||||
foreignColl2.dropIndex({b: 1});
|
||||
assert(
|
||||
_resultSetsEqualUnordered(noJoinOptResults, seedINJResults),
|
||||
"Results differ between no join opt and INJ",
|
||||
);
|
||||
} finally {
|
||||
// Reset flags.
|
||||
assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: false}));
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ bool isAggEligibleForJoinReordering(const MultipleCollectionAccessor& mca,
|
|||
return AggJoinModel::pipelineEligibleForJoinReordering(pipeline);
|
||||
}
|
||||
|
||||
bool indexIsValidForINLJ(std::shared_ptr<const IndexCatalogEntry> ice) {
|
||||
bool indexIsValidForINLJ(const std::shared_ptr<const IndexCatalogEntry>& ice) {
|
||||
auto desc = ice->descriptor();
|
||||
return !desc->isHashedIdIndex() && !desc->hidden() && !desc->isPartial() && !desc->isSparse() &&
|
||||
desc->collation().isEmpty() && !dynamic_cast<WildcardAccessMethod*>(ice->accessMethod());
|
||||
|
|
@ -121,8 +121,7 @@ AvailableIndexes extractINLJEligibleIndexes(const QuerySolutionMap& solns,
|
|||
AvailableIndexes perCollIdxs;
|
||||
for (const auto& [cq, _] : solns) {
|
||||
const auto& ns = cq->nss();
|
||||
auto it = perCollIdxs.find(ns);
|
||||
if (it != perCollIdxs.end()) {
|
||||
if (perCollIdxs.contains(ns)) {
|
||||
// We've already pre-processed this collection's indexes.
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,10 +31,21 @@
|
|||
|
||||
#include "mongo/bson/bsonobjbuilder.h"
|
||||
#include "mongo/db/query/compiler/optimizer/join/join_graph.h"
|
||||
#include "mongo/db/query/compiler/physical_model/query_solution/query_solution.h"
|
||||
#include "mongo/util/str.h"
|
||||
|
||||
namespace mongo::join_ordering {
|
||||
namespace {
|
||||
NodeSet getBitset(const JoinPlanNode& node) {
|
||||
return std::visit(
|
||||
OverloadedVisitor{[](const JoiningNode& join) { return join.bitset; },
|
||||
[](const INLJRHSNode& ip) { return NodeSet().set(ip.node); },
|
||||
[](const BaseNode& base) {
|
||||
return NodeSet().set(base.node);
|
||||
}},
|
||||
node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to pretty-print NodeSet.
|
||||
*/
|
||||
|
|
@ -57,20 +68,29 @@ std::string joinMethodToString(JoinMethod method) {
|
|||
|
||||
MONGO_UNREACHABLE_TASSERT(11336901);
|
||||
}
|
||||
|
||||
std::string joinNodeStringPrefix(const JoinPlanNode& node,
|
||||
size_t numNodesToPrint,
|
||||
std::string indentStr) {
|
||||
return str::stream() << indentStr << "[" << nodeSetToString(getBitset(node), numNodesToPrint)
|
||||
<< "]";
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string BaseNode::toString(size_t numNodesToPrint, std::string indentStr) const {
|
||||
return str::stream() << indentStr << "[" << nodeSetToString(bitset, numNodesToPrint) << "]["
|
||||
return str::stream() << joinNodeStringPrefix(*this, numNodesToPrint, indentStr) << "["
|
||||
<< nss.toString_forTest() << "] " << soln->summaryString();
|
||||
}
|
||||
|
||||
std::string JoiningNode::toString(size_t numNodesToPrint, std::string indentStr) const {
|
||||
auto ss = std::stringstream() << indentStr << "[" << nodeSetToString(bitset, numNodesToPrint)
|
||||
<< "] ";
|
||||
const auto methodStr = joinMethodToString(method);
|
||||
std::string INLJRHSNode::toString(size_t numNodesToPrint, std::string indentStr) const {
|
||||
return str::stream() << joinNodeStringPrefix(*this, numNodesToPrint, indentStr) << "["
|
||||
<< nss.toString_forTest() << "] INDEX_PROBE "
|
||||
<< entry->descriptor()->keyPattern();
|
||||
}
|
||||
|
||||
ss << methodStr;
|
||||
return ss.str();
|
||||
std::string JoiningNode::toString(size_t numNodesToPrint, std::string indentStr) const {
|
||||
return str::stream() << joinNodeStringPrefix(*this, numNodesToPrint, indentStr) << " "
|
||||
<< joinMethodToString(method);
|
||||
}
|
||||
|
||||
std::string JoinSubset::toString(size_t numNodesToPrint) const {
|
||||
|
|
@ -91,11 +111,19 @@ JoinPlanNodeId JoinPlanNodeRegistry::registerJoinNode(const JoinSubset& subset,
|
|||
return id;
|
||||
}
|
||||
|
||||
JoinPlanNodeId JoinPlanNodeRegistry::registerBaseNode(const JoinSubset& subset,
|
||||
JoinPlanNodeId JoinPlanNodeRegistry::registerBaseNode(NodeId node,
|
||||
const QuerySolution* soln,
|
||||
const NamespaceString& nss) {
|
||||
tassert(11371702, "Expected an initialized qsn", soln);
|
||||
JoinPlanNodeId id = _allJoinPlans.size();
|
||||
_allJoinPlans.emplace_back(BaseNode{soln, nss, subset.subset});
|
||||
_allJoinPlans.emplace_back(BaseNode{soln, nss, node});
|
||||
return id;
|
||||
}
|
||||
|
||||
JoinPlanNodeId JoinPlanNodeRegistry::registerINLJRHSNode(
|
||||
NodeId node, std::shared_ptr<const IndexCatalogEntry> entry, const NamespaceString& nss) {
|
||||
JoinPlanNodeId id = _allJoinPlans.size();
|
||||
_allJoinPlans.emplace_back(INLJRHSNode{std::move(entry), nss, node});
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
@ -108,6 +136,9 @@ std::string JoinPlanNodeRegistry::joinPlanNodeToString(JoinPlanNodeId nodeId,
|
|||
[&indentStr, &ss, numNodesToPrint](const BaseNode& n) {
|
||||
ss << n.toString(numNodesToPrint, indentStr);
|
||||
},
|
||||
[&indentStr, &ss, numNodesToPrint](const INLJRHSNode& n) {
|
||||
ss << n.toString(numNodesToPrint, indentStr);
|
||||
},
|
||||
[this, &indentStr, &ss, numNodesToPrint](const JoiningNode& n) {
|
||||
std::string nxtIndent = str::stream() << indentStr + " ";
|
||||
ss << n.toString(numNodesToPrint, indentStr) << "\n"
|
||||
|
|
@ -135,24 +166,34 @@ std::string JoinPlanNodeRegistry::joinPlansToString(const JoinPlans& plans,
|
|||
}
|
||||
|
||||
NodeSet JoinPlanNodeRegistry::getBitset(JoinPlanNodeId id) const {
|
||||
return std::visit([](const auto& n) { return n.bitset; }, get(id));
|
||||
return std::visit(
|
||||
OverloadedVisitor{[](const JoiningNode& join) { return join.bitset; },
|
||||
[](const INLJRHSNode& ip) { return NodeSet().set(ip.node); },
|
||||
[](const BaseNode& base) {
|
||||
return NodeSet().set(base.node);
|
||||
}},
|
||||
get(id));
|
||||
}
|
||||
|
||||
BSONObj JoinPlanNodeRegistry::joinPlanNodeToBSON(JoinPlanNodeId nodeId,
|
||||
size_t numNodesToPrint) const {
|
||||
return std::visit(
|
||||
OverloadedVisitor{[this, numNodesToPrint](const JoiningNode& join) {
|
||||
return BSON("subset"
|
||||
<< nodeSetToString(join.bitset, numNodesToPrint)
|
||||
<< "method" << joinMethodToString(join.method) << "left"
|
||||
<< joinPlanNodeToBSON(join.left, numNodesToPrint)
|
||||
<< "right"
|
||||
<< joinPlanNodeToBSON(join.right, numNodesToPrint));
|
||||
},
|
||||
[numNodesToPrint](const BaseNode& base) {
|
||||
return BSON("subset" << nodeSetToString(base.bitset, numNodesToPrint)
|
||||
<< "accessPath" << base.soln->summaryString());
|
||||
}},
|
||||
OverloadedVisitor{
|
||||
[this, numNodesToPrint](const JoiningNode& join) {
|
||||
return BSON("subset" << nodeSetToString(join.bitset, numNodesToPrint) << "method"
|
||||
<< joinMethodToString(join.method) << "left"
|
||||
<< joinPlanNodeToBSON(join.left, numNodesToPrint) << "right"
|
||||
<< joinPlanNodeToBSON(join.right, numNodesToPrint));
|
||||
},
|
||||
[numNodesToPrint](const INLJRHSNode& ip) {
|
||||
return BSON("subset" << nodeSetToString(ip.node, numNodesToPrint) << "accessPath"
|
||||
<< (str::stream() << "INDEX_PROBE "
|
||||
<< ip.entry->descriptor()->keyPattern()));
|
||||
},
|
||||
[numNodesToPrint](const BaseNode& base) {
|
||||
return BSON("subset" << nodeSetToString(base.node, numNodesToPrint) << "accessPath"
|
||||
<< base.soln->summaryString());
|
||||
}},
|
||||
get(nodeId));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "mongo/db/namespace_string.h"
|
||||
#include "mongo/db/query/compiler/optimizer/join/join_graph.h"
|
||||
#include "mongo/db/query/compiler/physical_model/query_solution/query_solution.h"
|
||||
#include "mongo/db/query/util/bitset_util.h"
|
||||
#include "mongo/util/modules.h"
|
||||
|
||||
#include <variant>
|
||||
|
|
@ -40,9 +41,10 @@ namespace mongo::join_ordering {
|
|||
// Forward declarations.
|
||||
struct JoiningNode;
|
||||
struct BaseNode;
|
||||
struct INLJRHSNode;
|
||||
|
||||
using JoinPlanNodeId = size_t;
|
||||
using JoinPlanNode = std::variant<JoiningNode, BaseNode>;
|
||||
using JoinPlanNode = std::variant<JoiningNode, BaseNode, INLJRHSNode>;
|
||||
using JoinPlans = std::vector<JoinPlanNodeId>;
|
||||
|
||||
/**
|
||||
|
|
@ -64,6 +66,11 @@ struct JoinSubset {
|
|||
return subset.count() == 1;
|
||||
}
|
||||
|
||||
NodeId getNodeId() const {
|
||||
tassert(11371703, "Must have just one node", isBaseCollectionAccess());
|
||||
return (NodeId)*begin(subset);
|
||||
}
|
||||
|
||||
inline JoinPlanNodeId bestPlan() const {
|
||||
tassert(11336908, "Expected bestPlanIndex < plans.size()", bestPlanIndex < plans.size());
|
||||
return plans[bestPlanIndex];
|
||||
|
|
@ -99,11 +106,29 @@ enum class JoinMethod {
|
|||
struct BaseNode {
|
||||
// Pointer to best access path obtained by CBR.
|
||||
const QuerySolution* soln;
|
||||
|
||||
// Namespace this access path corresponds to.
|
||||
const NamespaceString& nss;
|
||||
|
||||
// Keeps a copy of the bitset representing the subgraph this originated from.
|
||||
const NodeSet bitset;
|
||||
// Corresponds to node in the graph this represents a base table access to.
|
||||
const NodeId node;
|
||||
|
||||
std::string toString(size_t numNodesToPrint = kMaxNodesInJoin,
|
||||
std::string indentStr = "") const;
|
||||
};
|
||||
|
||||
/**
|
||||
* A JoinPlan node representing the right hand side of a INLJ join (an index probe).
|
||||
*/
|
||||
struct INLJRHSNode {
|
||||
// The index that will be used to construct an IndexProbe QSN.
|
||||
std::shared_ptr<const IndexCatalogEntry> entry;
|
||||
|
||||
// Namespace this access path corresponds to.
|
||||
const NamespaceString& nss;
|
||||
|
||||
// Corresponds to node in the graph this represents a base table access to.
|
||||
const NodeId node;
|
||||
|
||||
std::string toString(size_t numNodesToPrint = kMaxNodesInJoin,
|
||||
std::string indentStr = "") const;
|
||||
|
|
@ -146,9 +171,12 @@ public:
|
|||
JoinMethod method,
|
||||
JoinPlanNodeId left,
|
||||
JoinPlanNodeId right);
|
||||
JoinPlanNodeId registerBaseNode(const JoinSubset& subset,
|
||||
JoinPlanNodeId registerBaseNode(NodeId node,
|
||||
const QuerySolution* soln,
|
||||
const NamespaceString& nss);
|
||||
JoinPlanNodeId registerINLJRHSNode(NodeId node,
|
||||
std::shared_ptr<const IndexCatalogEntry> entry,
|
||||
const NamespaceString& nss);
|
||||
|
||||
const JoinPlanNode& get(JoinPlanNodeId id) const {
|
||||
return _allJoinPlans[id];
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@
|
|||
#include "mongo/db/query/compiler/optimizer/join/plan_enumerator_helpers.h"
|
||||
#include "mongo/logv2/log.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery
|
||||
|
||||
namespace mongo::join_ordering {
|
||||
|
|
@ -52,9 +50,10 @@ bool PlanEnumeratorContext::canPlanBeEnumerated(PlanTreeShape type,
|
|||
const JoinSubset& left,
|
||||
const JoinSubset& right,
|
||||
const JoinSubset& subset) const {
|
||||
if (method == JoinMethod::NLJ && !right.isBaseCollectionAccess()) {
|
||||
// NLJ plans perform poorly when the right hand side is not a collection access- don't
|
||||
// enumerate this plan.
|
||||
if ((method == JoinMethod::NLJ || method == JoinMethod::INLJ) &&
|
||||
!right.isBaseCollectionAccess()) {
|
||||
// NLJ plans perform poorly when the right hand side is not a collection access, while INLJ
|
||||
// requires the right side to be a base table access. Don't enumerate this plan.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -103,8 +102,8 @@ bool PlanEnumeratorContext::canPlanBeEnumerated(PlanTreeShape type,
|
|||
*/
|
||||
const auto& leftJoin = _registry.getAs<JoiningNode>(left.bestPlan());
|
||||
return _registry.isOfType<JoiningNode>(leftJoin.right) ||
|
||||
(_registry.isOfType<BaseNode>(leftJoin.right) &&
|
||||
_registry.isOfType<BaseNode>(leftJoin.left));
|
||||
(!_registry.isOfType<JoiningNode>(leftJoin.right) &&
|
||||
!_registry.isOfType<JoiningNode>(leftJoin.left));
|
||||
|
||||
} else if (!right.isBaseCollectionAccess()) {
|
||||
/**
|
||||
|
|
@ -126,8 +125,8 @@ bool PlanEnumeratorContext::canPlanBeEnumerated(PlanTreeShape type,
|
|||
*/
|
||||
const auto& rightJoin = _registry.getAs<JoiningNode>(right.bestPlan());
|
||||
return _registry.isOfType<JoiningNode>(rightJoin.left) ||
|
||||
(_registry.isOfType<BaseNode>(rightJoin.right) &&
|
||||
_registry.isOfType<BaseNode>(rightJoin.left));
|
||||
(!_registry.isOfType<JoiningNode>(rightJoin.right) &&
|
||||
!_registry.isOfType<JoiningNode>(rightJoin.left));
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -147,9 +146,27 @@ void PlanEnumeratorContext::addJoinPlan(PlanTreeShape type,
|
|||
if (!canPlanBeEnumerated(type, method, left, right, subset)) {
|
||||
return;
|
||||
}
|
||||
// TODO SERVER-113059: Rudimentary cost metric/tracking.
|
||||
subset.plans.push_back(
|
||||
_registry.registerJoinNode(subset, method, left.bestPlan(), right.bestPlan()));
|
||||
|
||||
if (method == JoinMethod::INLJ) {
|
||||
// TODO SERVER-115093: Change this to an equality tassert once we break cycles.
|
||||
tassert(11371701, "Expected at least one edge", edges.size() >= 1);
|
||||
auto edge = edges[0];
|
||||
auto ie = bestIndexSatisfyingJoinPredicates(
|
||||
_ctx, (NodeId)*begin(right.subset), _ctx.joinGraph.getEdge(edge));
|
||||
if (ie) {
|
||||
const auto nodeId = right.getNodeId();
|
||||
const auto& nss = _ctx.joinGraph.accessPathAt(nodeId)->nss();
|
||||
auto rhs = _registry.registerINLJRHSNode(nodeId, ie, nss);
|
||||
subset.plans.push_back(
|
||||
_registry.registerJoinNode(subset, method, left.bestPlan(), rhs));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// TODO SERVER-113059: Rudimentary cost metric/tracking.
|
||||
subset.plans.push_back(
|
||||
_registry.registerJoinNode(subset, method, left.bestPlan(), right.bestPlan()));
|
||||
}
|
||||
|
||||
LOGV2_DEBUG(11336912,
|
||||
5,
|
||||
|
|
@ -179,6 +196,7 @@ void PlanEnumeratorContext::enumerateJoinPlans(PlanTreeShape type,
|
|||
return;
|
||||
}
|
||||
|
||||
addJoinPlan(type, JoinMethod::INLJ, left, right, joinEdges, cur);
|
||||
addJoinPlan(type, JoinMethod::HJ, left, right, joinEdges, cur);
|
||||
addJoinPlan(type, JoinMethod::NLJ, left, right, joinEdges, cur);
|
||||
}
|
||||
|
|
@ -198,12 +216,12 @@ void PlanEnumeratorContext::enumerateJoinSubsets(PlanTreeShape type) {
|
|||
const auto* qsn = _ctx.cbrCqQsns.at(cq).get();
|
||||
_joinSubsets[kBaseLevel].push_back(JoinSubset(NodeSet{}.set(i)));
|
||||
_joinSubsets[kBaseLevel].back().plans = {
|
||||
_registry.registerBaseNode(_joinSubsets[kBaseLevel].back(), qsn, cq->nss())};
|
||||
_registry.registerBaseNode((NodeId)i, qsn, cq->nss())};
|
||||
}
|
||||
|
||||
// Initialize the rest of the joinSubsets.
|
||||
for (int level = 1; level < numNodes; ++level) {
|
||||
const auto& joinSubsetsPrevLevel = _joinSubsets[level - 1];
|
||||
auto& joinSubsetsPrevLevel = _joinSubsets[level - 1];
|
||||
auto& joinSubsetsCurrLevel = _joinSubsets[level];
|
||||
// Preallocate entries for all subsets in the current level.
|
||||
joinSubsetsCurrLevel.reserve(cs.next());
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ DEATH_TEST(PlanEnumeratorHelpersDeathTest, TooManyInvocationsOfCombinationSequen
|
|||
|
||||
class JoinPlanEnumeratorTest : public JoinOrderingTestFixture {
|
||||
public:
|
||||
void initGraph(size_t numNodes) {
|
||||
void initGraph(size_t numNodes, bool withIndexes = false) {
|
||||
for (size_t i = 0; i < numNodes; i++) {
|
||||
auto nss =
|
||||
NamespaceString::createNamespaceString_forTest("test", str::stream() << "nss" << i);
|
||||
|
|
@ -95,19 +95,27 @@ public:
|
|||
jCtx.cbrCqQsns.insert(
|
||||
{cq.get(), makeCollScanPlan(nss, cq->getPrimaryMatchExpression()->clone())});
|
||||
ASSERT_TRUE(graph.addNode(nss, std::move(cq), boost::none).has_value());
|
||||
|
||||
if (withIndexes) {
|
||||
jCtx.perCollIdxs.emplace(
|
||||
nss, makeIndexCatalogEntries({BSON(fieldName << (i % 2 ? 1 : -1))}));
|
||||
}
|
||||
|
||||
resolvedPaths.emplace_back(ResolvedPath{(NodeId)i, FieldPath(fieldName)});
|
||||
}
|
||||
}
|
||||
|
||||
void testLargeSubset(unittest::GoldenTestContext* goldenCtx,
|
||||
PlanTreeShape shape,
|
||||
size_t numNodes) {
|
||||
initGraph(numNodes);
|
||||
size_t numNodes,
|
||||
bool withIndexes = false) {
|
||||
initGraph(numNodes, withIndexes);
|
||||
|
||||
for (size_t i = 1; i < numNodes; ++i) {
|
||||
// Make the graph fully connected in order to ensure we generate as many plans as
|
||||
// possible.
|
||||
for (size_t j = 0; j < i; ++j) {
|
||||
ASSERT_TRUE(graph.addSimpleEqualityEdge((NodeId)j, (NodeId)i, 0, 1).has_value());
|
||||
ASSERT_TRUE(graph.addSimpleEqualityEdge((NodeId)j, (NodeId)i, j, i).has_value());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -290,16 +298,31 @@ TEST_F(JoinPlanEnumeratorTest, LeftDeep8Nodes) {
|
|||
testLargeSubset(&goldenCtx, PlanTreeShape::LEFT_DEEP, 8);
|
||||
}
|
||||
|
||||
TEST_F(JoinPlanEnumeratorTest, LeftDeep8NodesINLJ) {
|
||||
unittest::GoldenTestContext goldenCtx(&goldenTestConfig);
|
||||
testLargeSubset(&goldenCtx, PlanTreeShape::LEFT_DEEP, 8, true /* withIndexes */);
|
||||
}
|
||||
|
||||
TEST_F(JoinPlanEnumeratorTest, RightDeep8Nodes) {
|
||||
unittest::GoldenTestContext goldenCtx(&goldenTestConfig);
|
||||
testLargeSubset(&goldenCtx, PlanTreeShape::RIGHT_DEEP, 8);
|
||||
}
|
||||
|
||||
TEST_F(JoinPlanEnumeratorTest, RightDeep8NodesINLJ) {
|
||||
unittest::GoldenTestContext goldenCtx(&goldenTestConfig);
|
||||
testLargeSubset(&goldenCtx, PlanTreeShape::RIGHT_DEEP, 8, true /* withIndexes */);
|
||||
}
|
||||
|
||||
TEST_F(JoinPlanEnumeratorTest, ZigZag8Nodes) {
|
||||
unittest::GoldenTestContext goldenCtx(&goldenTestConfig);
|
||||
testLargeSubset(&goldenCtx, PlanTreeShape::ZIG_ZAG, 8);
|
||||
}
|
||||
|
||||
TEST_F(JoinPlanEnumeratorTest, ZigZag8NodesINLJ) {
|
||||
unittest::GoldenTestContext goldenCtx(&goldenTestConfig);
|
||||
testLargeSubset(&goldenCtx, PlanTreeShape::ZIG_ZAG, 8, true /* withIndexes */);
|
||||
}
|
||||
|
||||
TEST_F(JoinPlanEnumeratorTest, InitialzeLargeSubsets) {
|
||||
testLargeSubset(nullptr /* No golden test here. */, PlanTreeShape::LEFT_DEEP, 15);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "mongo/db/query/compiler/optimizer/join/reorder_joins.h"
|
||||
|
||||
#include "mongo/db/query/compiler/optimizer/join/join_graph.h"
|
||||
#include "mongo/db/query/compiler/optimizer/join/join_plan.h"
|
||||
#include "mongo/db/query/compiler/optimizer/join/join_reordering_context.h"
|
||||
#include "mongo/db/query/compiler/optimizer/join/plan_enumerator.h"
|
||||
#include "mongo/db/query/compiler/optimizer/join/plan_enumerator_helpers.h"
|
||||
|
|
@ -173,6 +174,10 @@ std::unique_ptr<QuerySolutionNode> buildQSNFromJoinPlan(const JoinReorderingCont
|
|||
[&qsn](const BaseNode& base) {
|
||||
// TODO SERVER-111913: Avoid this clone
|
||||
qsn = base.soln->root()->clone();
|
||||
},
|
||||
[&ctx, &qsn, ®istry](const INLJRHSNode& ip) {
|
||||
qsn = createIndexProbeQSN(ctx.joinGraph.getNode(ip.node),
|
||||
ip.entry);
|
||||
}},
|
||||
registry.get(nodeId));
|
||||
return qsn;
|
||||
|
|
@ -187,9 +192,11 @@ NodeId getLeftmostNodeIdOfJoinPlan(const JoinReorderingContext& ctx,
|
|||
return getLeftmostNodeIdOfJoinPlan(
|
||||
ctx, join.left, registry);
|
||||
},
|
||||
[](const BaseNode& base) {
|
||||
BitsetIterator<kMaxNodesInJoin> it = begin(base.bitset);
|
||||
return (NodeId)*it;
|
||||
[](const BaseNode& base) { return base.node; },
|
||||
[](const INLJRHSNode&) {
|
||||
// By definition, this should never happen.
|
||||
MONGO_UNREACHABLE_TASSERT(11371704);
|
||||
return (NodeId)0;
|
||||
}},
|
||||
registry.get(nodeId));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@
|
|||
#include "mongo/db/query/compiler/optimizer/join/join_reordering_context.h"
|
||||
#include "mongo/db/query/compiler/optimizer/join/plan_enumerator_helpers.h"
|
||||
#include "mongo/db/query/compiler/optimizer/join/unit_test_helpers.h"
|
||||
#include "mongo/db/shard_role/shard_catalog/index_catalog_entry.h"
|
||||
#include "mongo/db/shard_role/shard_catalog/index_catalog_entry_mock.h"
|
||||
#include "mongo/db/shard_role/shard_catalog/index_catalog_mock.h"
|
||||
#include "mongo/unittest/golden_test.h"
|
||||
#include "mongo/unittest/unittest.h"
|
||||
|
||||
|
|
@ -55,36 +52,6 @@ QuerySolutionMap cloneSolnMap(const QuerySolutionMap& qsm) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
IndexDescriptor makeIndexDescriptor(BSONObj indexSpec) {
|
||||
|
||||
IndexSpec spec;
|
||||
spec.version(2).name("name").addKeys(indexSpec);
|
||||
return IndexDescriptor(IndexNames::BTREE, spec.toBSON());
|
||||
}
|
||||
|
||||
IndexCatalogEntryMock makeIndexCatalogEntry(BSONObj indexSpec) {
|
||||
return IndexCatalogEntryMock{nullptr /*opCtx*/,
|
||||
CollectionPtr{},
|
||||
"" /*ident*/,
|
||||
makeIndexDescriptor(indexSpec),
|
||||
false /*isFrozen*/};
|
||||
}
|
||||
|
||||
IndexCatalogMock makeIndexCatalog(const std::vector<BSONObj>& keyPatterns) {
|
||||
IndexCatalogMock catalog;
|
||||
for (auto&& kp : keyPatterns) {
|
||||
catalog.createIndexEntry(nullptr, nullptr, makeIndexDescriptor(kp), {});
|
||||
}
|
||||
return catalog;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<const IndexCatalogEntry>> makeIndexCatalogEntries(
|
||||
const std::vector<BSONObj>& keyPatterns) {
|
||||
auto ic = makeIndexCatalog(keyPatterns);
|
||||
std::vector<std::shared_ptr<const IndexCatalogEntry>> idxs(keyPatterns.size());
|
||||
return ic.getEntriesShared(IndexCatalog::InclusionPolicy::kReady);
|
||||
}
|
||||
|
||||
class ReorderGraphTest : public JoinOrderingTestFixture {
|
||||
protected:
|
||||
// Helper struct for intializing a namespace, its embedding, any residual filter, and indexes
|
||||
|
|
|
|||
|
|
@ -36,6 +36,35 @@ namespace mongo::join_ordering {
|
|||
|
||||
using namespace cost_based_ranker;
|
||||
|
||||
IndexDescriptor makeIndexDescriptor(BSONObj indexSpec) {
|
||||
IndexSpec spec;
|
||||
spec.version(2).name("name").addKeys(indexSpec);
|
||||
return IndexDescriptor(IndexNames::BTREE, spec.toBSON());
|
||||
}
|
||||
|
||||
IndexCatalogEntryMock makeIndexCatalogEntry(BSONObj indexSpec) {
|
||||
return IndexCatalogEntryMock{nullptr /*opCtx*/,
|
||||
CollectionPtr{},
|
||||
"" /*ident*/,
|
||||
makeIndexDescriptor(indexSpec),
|
||||
false /*isFrozen*/};
|
||||
}
|
||||
|
||||
IndexCatalogMock makeIndexCatalog(const std::vector<BSONObj>& keyPatterns) {
|
||||
IndexCatalogMock catalog;
|
||||
for (auto&& kp : keyPatterns) {
|
||||
catalog.createIndexEntry(nullptr, nullptr, makeIndexDescriptor(kp), {});
|
||||
}
|
||||
return catalog;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<const IndexCatalogEntry>> makeIndexCatalogEntries(
|
||||
const std::vector<BSONObj>& keyPatterns) {
|
||||
auto ic = makeIndexCatalog(keyPatterns);
|
||||
std::vector<std::shared_ptr<const IndexCatalogEntry>> idxs(keyPatterns.size());
|
||||
return ic.getEntriesShared(IndexCatalog::InclusionPolicy::kReady);
|
||||
}
|
||||
|
||||
MultipleCollectionAccessor multipleCollectionAccessor(OperationContext* opCtx,
|
||||
std::vector<NamespaceString> namespaces) {
|
||||
auto mainAcquisitionReq = CollectionAcquisitionRequest::fromOpCtx(
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@
|
|||
#include "mongo/db/query/compiler/optimizer/join/join_reordering_context.h"
|
||||
#include "mongo/db/query/multiple_collection_accessor.h"
|
||||
#include "mongo/db/shard_role/shard_catalog/catalog_test_fixture.h"
|
||||
#include "mongo/db/shard_role/shard_catalog/index_catalog_entry.h"
|
||||
#include "mongo/db/shard_role/shard_catalog/index_catalog_entry_mock.h"
|
||||
#include "mongo/db/shard_role/shard_catalog/index_catalog_mock.h"
|
||||
#include "mongo/unittest/golden_test_base.h"
|
||||
#include "mongo/util/modules.h"
|
||||
|
||||
|
|
@ -46,6 +49,16 @@ namespace mongo::join_ordering {
|
|||
MultipleCollectionAccessor multipleCollectionAccessor(OperationContext* opCtx,
|
||||
std::vector<NamespaceString> namespaces);
|
||||
|
||||
/**
|
||||
* Helpers used to mock index information for unit tests without requiring a
|
||||
* MultipleCollectionAccessor.
|
||||
*/
|
||||
IndexDescriptor makeIndexDescriptor(BSONObj indexSpec);
|
||||
IndexCatalogEntryMock makeIndexCatalogEntry(BSONObj indexSpec);
|
||||
IndexCatalogMock makeIndexCatalog(const std::vector<BSONObj>& keyPatterns);
|
||||
std::vector<std::shared_ptr<const IndexCatalogEntry>> makeIndexCatalogEntries(
|
||||
const std::vector<BSONObj>& keyPatterns);
|
||||
|
||||
/**
|
||||
* Text fixture with helpful functions for manipulating the catalog, constructing samples and
|
||||
* queries/QSNs.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,738 @@
|
|||
Level 0:
|
||||
00000001, 00000010, 00000100, 00001000, 00010000, 00100000, 01000000, 10000000
|
||||
Level 1:
|
||||
00000011, 00000101, 00001001, 00010001, 00100001, 01000001, 10000001, 00000110, 00001010, 00010010, 00100010, 01000010, 10000010, 00001100, 00010100, 00100100, 01000100, 10000100, 00011000, 00101000, 01001000, 10001000, 00110000, 01010000, 10010000, 01100000, 10100000, 11000000
|
||||
Level 2:
|
||||
00000111, 00001011, 00010011, 00100011, 01000011, 10000011, 00001101, 00010101, 00100101, 01000101, 10000101, 00011001, 00101001, 01001001, 10001001, 00110001, 01010001, 10010001, 01100001, 10100001, 11000001, 00001110, 00010110, 00100110, 01000110, 10000110, 00011010, 00101010, 01001010, 10001010, 00110010, 01010010, 10010010, 01100010, 10100010, 11000010, 00011100, 00101100, 01001100, 10001100, 00110100, 01010100, 10010100, 01100100, 10100100, 11000100, 00111000, 01011000, 10011000, 01101000, 10101000, 11001000, 01110000, 10110000, 11010000, 11100000
|
||||
Level 3:
|
||||
00001111, 00010111, 00100111, 01000111, 10000111, 00011011, 00101011, 01001011, 10001011, 00110011, 01010011, 10010011, 01100011, 10100011, 11000011, 00011101, 00101101, 01001101, 10001101, 00110101, 01010101, 10010101, 01100101, 10100101, 11000101, 00111001, 01011001, 10011001, 01101001, 10101001, 11001001, 01110001, 10110001, 11010001, 11100001, 00011110, 00101110, 01001110, 10001110, 00110110, 01010110, 10010110, 01100110, 10100110, 11000110, 00111010, 01011010, 10011010, 01101010, 10101010, 11001010, 01110010, 10110010, 11010010, 11100010, 00111100, 01011100, 10011100, 01101100, 10101100, 11001100, 01110100, 10110100, 11010100, 11100100, 01111000, 10111000, 11011000, 11101000, 11110000
|
||||
Level 4:
|
||||
00011111, 00101111, 01001111, 10001111, 00110111, 01010111, 10010111, 01100111, 10100111, 11000111, 00111011, 01011011, 10011011, 01101011, 10101011, 11001011, 01110011, 10110011, 11010011, 11100011, 00111101, 01011101, 10011101, 01101101, 10101101, 11001101, 01110101, 10110101, 11010101, 11100101, 01111001, 10111001, 11011001, 11101001, 11110001, 00111110, 01011110, 10011110, 01101110, 10101110, 11001110, 01110110, 10110110, 11010110, 11100110, 01111010, 10111010, 11011010, 11101010, 11110010, 01111100, 10111100, 11011100, 11101100, 11110100, 11111000
|
||||
Level 5:
|
||||
00111111, 01011111, 10011111, 01101111, 10101111, 11001111, 01110111, 10110111, 11010111, 11100111, 01111011, 10111011, 11011011, 11101011, 11110011, 01111101, 10111101, 11011101, 11101101, 11110101, 11111001, 01111110, 10111110, 11011110, 11101110, 11110110, 11111010, 11111100
|
||||
Level 6:
|
||||
01111111, 10111111, 11011111, 11101111, 11110111, 11111011, 11111101, 11111110
|
||||
Level 7:
|
||||
11111111
|
||||
|
||||
Output plans (best plan 0):
|
||||
0.[11111111] INLJ
|
||||
-> left:
|
||||
[01111111] INLJ
|
||||
-> left:
|
||||
[00111111] INLJ
|
||||
-> left:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
|
||||
1.[11111111] HJ
|
||||
-> left:
|
||||
[01111111] INLJ
|
||||
-> left:
|
||||
[00111111] INLJ
|
||||
-> left:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] COLLSCAN
|
||||
|
||||
2.[11111111] NLJ
|
||||
-> left:
|
||||
[01111111] INLJ
|
||||
-> left:
|
||||
[00111111] INLJ
|
||||
-> left:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] COLLSCAN
|
||||
|
||||
3.[11111111] INLJ
|
||||
-> left:
|
||||
[10111111] INLJ
|
||||
-> left:
|
||||
[00111111] INLJ
|
||||
-> left:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
|
||||
4.[11111111] HJ
|
||||
-> left:
|
||||
[10111111] INLJ
|
||||
-> left:
|
||||
[00111111] INLJ
|
||||
-> left:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
|
||||
5.[11111111] NLJ
|
||||
-> left:
|
||||
[10111111] INLJ
|
||||
-> left:
|
||||
[00111111] INLJ
|
||||
-> left:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
|
||||
6.[11111111] INLJ
|
||||
-> left:
|
||||
[11011111] INLJ
|
||||
-> left:
|
||||
[01011111] INLJ
|
||||
-> left:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
|
||||
7.[11111111] HJ
|
||||
-> left:
|
||||
[11011111] INLJ
|
||||
-> left:
|
||||
[01011111] INLJ
|
||||
-> left:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
|
||||
8.[11111111] NLJ
|
||||
-> left:
|
||||
[11011111] INLJ
|
||||
-> left:
|
||||
[01011111] INLJ
|
||||
-> left:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
|
||||
9.[11111111] INLJ
|
||||
-> left:
|
||||
[11101111] INLJ
|
||||
-> left:
|
||||
[01101111] INLJ
|
||||
-> left:
|
||||
[00101111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
|
||||
10.[11111111] HJ
|
||||
-> left:
|
||||
[11101111] INLJ
|
||||
-> left:
|
||||
[01101111] INLJ
|
||||
-> left:
|
||||
[00101111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
|
||||
11.[11111111] NLJ
|
||||
-> left:
|
||||
[11101111] INLJ
|
||||
-> left:
|
||||
[01101111] INLJ
|
||||
-> left:
|
||||
[00101111] INLJ
|
||||
-> left:
|
||||
[00001111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
|
||||
12.[11111111] INLJ
|
||||
-> left:
|
||||
[11110111] INLJ
|
||||
-> left:
|
||||
[01110111] INLJ
|
||||
-> left:
|
||||
[00110111] INLJ
|
||||
-> left:
|
||||
[00010111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
|
||||
13.[11111111] HJ
|
||||
-> left:
|
||||
[11110111] INLJ
|
||||
-> left:
|
||||
[01110111] INLJ
|
||||
-> left:
|
||||
[00110111] INLJ
|
||||
-> left:
|
||||
[00010111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
|
||||
14.[11111111] NLJ
|
||||
-> left:
|
||||
[11110111] INLJ
|
||||
-> left:
|
||||
[01110111] INLJ
|
||||
-> left:
|
||||
[00110111] INLJ
|
||||
-> left:
|
||||
[00010111] INLJ
|
||||
-> left:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
|
||||
15.[11111111] INLJ
|
||||
-> left:
|
||||
[11111011] INLJ
|
||||
-> left:
|
||||
[01111011] INLJ
|
||||
-> left:
|
||||
[00111011] INLJ
|
||||
-> left:
|
||||
[00011011] INLJ
|
||||
-> left:
|
||||
[00001011] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
|
||||
16.[11111111] HJ
|
||||
-> left:
|
||||
[11111011] INLJ
|
||||
-> left:
|
||||
[01111011] INLJ
|
||||
-> left:
|
||||
[00111011] INLJ
|
||||
-> left:
|
||||
[00011011] INLJ
|
||||
-> left:
|
||||
[00001011] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] COLLSCAN
|
||||
|
||||
17.[11111111] NLJ
|
||||
-> left:
|
||||
[11111011] INLJ
|
||||
-> left:
|
||||
[01111011] INLJ
|
||||
-> left:
|
||||
[00111011] INLJ
|
||||
-> left:
|
||||
[00011011] INLJ
|
||||
-> left:
|
||||
[00001011] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] COLLSCAN
|
||||
|
||||
18.[11111111] INLJ
|
||||
-> left:
|
||||
[11111101] INLJ
|
||||
-> left:
|
||||
[01111101] INLJ
|
||||
-> left:
|
||||
[00111101] INLJ
|
||||
-> left:
|
||||
[00011101] INLJ
|
||||
-> left:
|
||||
[00001101] INLJ
|
||||
-> left:
|
||||
[00000101] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
|
||||
19.[11111111] HJ
|
||||
-> left:
|
||||
[11111101] INLJ
|
||||
-> left:
|
||||
[01111101] INLJ
|
||||
-> left:
|
||||
[00111101] INLJ
|
||||
-> left:
|
||||
[00011101] INLJ
|
||||
-> left:
|
||||
[00001101] INLJ
|
||||
-> left:
|
||||
[00000101] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00000010][test.nss1] COLLSCAN
|
||||
|
||||
20.[11111111] NLJ
|
||||
-> left:
|
||||
[11111101] INLJ
|
||||
-> left:
|
||||
[01111101] INLJ
|
||||
-> left:
|
||||
[00111101] INLJ
|
||||
-> left:
|
||||
[00011101] INLJ
|
||||
-> left:
|
||||
[00001101] INLJ
|
||||
-> left:
|
||||
[00000101] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00000010][test.nss1] COLLSCAN
|
||||
|
||||
21.[11111111] INLJ
|
||||
-> left:
|
||||
[11111110] INLJ
|
||||
-> left:
|
||||
[01111110] INLJ
|
||||
-> left:
|
||||
[00111110] INLJ
|
||||
-> left:
|
||||
[00011110] INLJ
|
||||
-> left:
|
||||
[00001110] INLJ
|
||||
-> left:
|
||||
[00000110] INLJ
|
||||
-> left:
|
||||
[00000010][test.nss1] COLLSCAN
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00000001][test.nss0] INDEX_PROBE { a0: -1 }
|
||||
|
||||
22.[11111111] HJ
|
||||
-> left:
|
||||
[11111110] INLJ
|
||||
-> left:
|
||||
[01111110] INLJ
|
||||
-> left:
|
||||
[00111110] INLJ
|
||||
-> left:
|
||||
[00011110] INLJ
|
||||
-> left:
|
||||
[00001110] INLJ
|
||||
-> left:
|
||||
[00000110] INLJ
|
||||
-> left:
|
||||
[00000010][test.nss1] COLLSCAN
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
|
||||
23.[11111111] NLJ
|
||||
-> left:
|
||||
[11111110] INLJ
|
||||
-> left:
|
||||
[01111110] INLJ
|
||||
-> left:
|
||||
[00111110] INLJ
|
||||
-> left:
|
||||
[00011110] INLJ
|
||||
-> left:
|
||||
[00001110] INLJ
|
||||
-> left:
|
||||
[00000110] INLJ
|
||||
-> left:
|
||||
[00000010][test.nss1] COLLSCAN
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
-> right:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
Level 0:
|
||||
00000001, 00000010, 00000100, 00001000, 00010000, 00100000, 01000000, 10000000
|
||||
Level 1:
|
||||
00000011, 00000101, 00001001, 00010001, 00100001, 01000001, 10000001, 00000110, 00001010, 00010010, 00100010, 01000010, 10000010, 00001100, 00010100, 00100100, 01000100, 10000100, 00011000, 00101000, 01001000, 10001000, 00110000, 01010000, 10010000, 01100000, 10100000, 11000000
|
||||
Level 2:
|
||||
00000111, 00001011, 00010011, 00100011, 01000011, 10000011, 00001101, 00010101, 00100101, 01000101, 10000101, 00011001, 00101001, 01001001, 10001001, 00110001, 01010001, 10010001, 01100001, 10100001, 11000001, 00001110, 00010110, 00100110, 01000110, 10000110, 00011010, 00101010, 01001010, 10001010, 00110010, 01010010, 10010010, 01100010, 10100010, 11000010, 00011100, 00101100, 01001100, 10001100, 00110100, 01010100, 10010100, 01100100, 10100100, 11000100, 00111000, 01011000, 10011000, 01101000, 10101000, 11001000, 01110000, 10110000, 11010000, 11100000
|
||||
Level 3:
|
||||
00001111, 00010111, 00100111, 01000111, 10000111, 00011011, 00101011, 01001011, 10001011, 00110011, 01010011, 10010011, 01100011, 10100011, 11000011, 00011101, 00101101, 01001101, 10001101, 00110101, 01010101, 10010101, 01100101, 10100101, 11000101, 00111001, 01011001, 10011001, 01101001, 10101001, 11001001, 01110001, 10110001, 11010001, 11100001, 00011110, 00101110, 01001110, 10001110, 00110110, 01010110, 10010110, 01100110, 10100110, 11000110, 00111010, 01011010, 10011010, 01101010, 10101010, 11001010, 01110010, 10110010, 11010010, 11100010, 00111100, 01011100, 10011100, 01101100, 10101100, 11001100, 01110100, 10110100, 11010100, 11100100, 01111000, 10111000, 11011000, 11101000, 11110000
|
||||
Level 4:
|
||||
00011111, 00101111, 01001111, 10001111, 00110111, 01010111, 10010111, 01100111, 10100111, 11000111, 00111011, 01011011, 10011011, 01101011, 10101011, 11001011, 01110011, 10110011, 11010011, 11100011, 00111101, 01011101, 10011101, 01101101, 10101101, 11001101, 01110101, 10110101, 11010101, 11100101, 01111001, 10111001, 11011001, 11101001, 11110001, 00111110, 01011110, 10011110, 01101110, 10101110, 11001110, 01110110, 10110110, 11010110, 11100110, 01111010, 10111010, 11011010, 11101010, 11110010, 01111100, 10111100, 11011100, 11101100, 11110100, 11111000
|
||||
Level 5:
|
||||
00111111, 01011111, 10011111, 01101111, 10101111, 11001111, 01110111, 10110111, 11010111, 11100111, 01111011, 10111011, 11011011, 11101011, 11110011, 01111101, 10111101, 11011101, 11101101, 11110101, 11111001, 01111110, 10111110, 11011110, 11101110, 11110110, 11111010, 11111100
|
||||
Level 6:
|
||||
01111111, 10111111, 11011111, 11101111, 11110111, 11111011, 11111101, 11111110
|
||||
Level 7:
|
||||
11111111
|
||||
|
||||
Output plans (best plan 0):
|
||||
0.[11111111] HJ
|
||||
-> left:
|
||||
[10000000][test.nss7] COLLSCAN
|
||||
-> right:
|
||||
[01111111] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00111111] HJ
|
||||
-> left:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
-> right:
|
||||
[00011111] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[00001111] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[00000111] HJ
|
||||
-> left:
|
||||
[00000100][test.nss2] COLLSCAN
|
||||
-> right:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
|
||||
1.[11111111] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[10111111] HJ
|
||||
-> left:
|
||||
[10000000][test.nss7] COLLSCAN
|
||||
-> right:
|
||||
[00111111] HJ
|
||||
-> left:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
-> right:
|
||||
[00011111] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[00001111] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[00000111] HJ
|
||||
-> left:
|
||||
[00000100][test.nss2] COLLSCAN
|
||||
-> right:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
|
||||
2.[11111111] HJ
|
||||
-> left:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
-> right:
|
||||
[11011111] HJ
|
||||
-> left:
|
||||
[10000000][test.nss7] COLLSCAN
|
||||
-> right:
|
||||
[01011111] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00011111] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[00001111] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[00000111] HJ
|
||||
-> left:
|
||||
[00000100][test.nss2] COLLSCAN
|
||||
-> right:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
|
||||
3.[11111111] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[11101111] HJ
|
||||
-> left:
|
||||
[10000000][test.nss7] COLLSCAN
|
||||
-> right:
|
||||
[01101111] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00101111] HJ
|
||||
-> left:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
-> right:
|
||||
[00001111] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[00000111] HJ
|
||||
-> left:
|
||||
[00000100][test.nss2] COLLSCAN
|
||||
-> right:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
|
||||
4.[11111111] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[11110111] HJ
|
||||
-> left:
|
||||
[10000000][test.nss7] COLLSCAN
|
||||
-> right:
|
||||
[01110111] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00110111] HJ
|
||||
-> left:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
-> right:
|
||||
[00010111] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[00000111] HJ
|
||||
-> left:
|
||||
[00000100][test.nss2] COLLSCAN
|
||||
-> right:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
|
||||
5.[11111111] HJ
|
||||
-> left:
|
||||
[00000100][test.nss2] COLLSCAN
|
||||
-> right:
|
||||
[11111011] HJ
|
||||
-> left:
|
||||
[10000000][test.nss7] COLLSCAN
|
||||
-> right:
|
||||
[01111011] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00111011] HJ
|
||||
-> left:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
-> right:
|
||||
[00011011] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[00001011] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
|
||||
6.[11111111] HJ
|
||||
-> left:
|
||||
[00000010][test.nss1] COLLSCAN
|
||||
-> right:
|
||||
[11111101] HJ
|
||||
-> left:
|
||||
[10000000][test.nss7] COLLSCAN
|
||||
-> right:
|
||||
[01111101] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00111101] HJ
|
||||
-> left:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
-> right:
|
||||
[00011101] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[00001101] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[00000101] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
|
||||
7.[11111111] HJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[11111110] HJ
|
||||
-> left:
|
||||
[10000000][test.nss7] COLLSCAN
|
||||
-> right:
|
||||
[01111110] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00111110] HJ
|
||||
-> left:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
-> right:
|
||||
[00011110] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[00001110] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[00000110] INLJ
|
||||
-> left:
|
||||
[00000010][test.nss1] COLLSCAN
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
Level 0:
|
||||
00000001, 00000010, 00000100, 00001000, 00010000, 00100000, 01000000, 10000000
|
||||
Level 1:
|
||||
00000011, 00000101, 00001001, 00010001, 00100001, 01000001, 10000001, 00000110, 00001010, 00010010, 00100010, 01000010, 10000010, 00001100, 00010100, 00100100, 01000100, 10000100, 00011000, 00101000, 01001000, 10001000, 00110000, 01010000, 10010000, 01100000, 10100000, 11000000
|
||||
Level 2:
|
||||
00000111, 00001011, 00010011, 00100011, 01000011, 10000011, 00001101, 00010101, 00100101, 01000101, 10000101, 00011001, 00101001, 01001001, 10001001, 00110001, 01010001, 10010001, 01100001, 10100001, 11000001, 00001110, 00010110, 00100110, 01000110, 10000110, 00011010, 00101010, 01001010, 10001010, 00110010, 01010010, 10010010, 01100010, 10100010, 11000010, 00011100, 00101100, 01001100, 10001100, 00110100, 01010100, 10010100, 01100100, 10100100, 11000100, 00111000, 01011000, 10011000, 01101000, 10101000, 11001000, 01110000, 10110000, 11010000, 11100000
|
||||
Level 3:
|
||||
00001111, 00010111, 00100111, 01000111, 10000111, 00011011, 00101011, 01001011, 10001011, 00110011, 01010011, 10010011, 01100011, 10100011, 11000011, 00011101, 00101101, 01001101, 10001101, 00110101, 01010101, 10010101, 01100101, 10100101, 11000101, 00111001, 01011001, 10011001, 01101001, 10101001, 11001001, 01110001, 10110001, 11010001, 11100001, 00011110, 00101110, 01001110, 10001110, 00110110, 01010110, 10010110, 01100110, 10100110, 11000110, 00111010, 01011010, 10011010, 01101010, 10101010, 11001010, 01110010, 10110010, 11010010, 11100010, 00111100, 01011100, 10011100, 01101100, 10101100, 11001100, 01110100, 10110100, 11010100, 11100100, 01111000, 10111000, 11011000, 11101000, 11110000
|
||||
Level 4:
|
||||
00011111, 00101111, 01001111, 10001111, 00110111, 01010111, 10010111, 01100111, 10100111, 11000111, 00111011, 01011011, 10011011, 01101011, 10101011, 11001011, 01110011, 10110011, 11010011, 11100011, 00111101, 01011101, 10011101, 01101101, 10101101, 11001101, 01110101, 10110101, 11010101, 11100101, 01111001, 10111001, 11011001, 11101001, 11110001, 00111110, 01011110, 10011110, 01101110, 10101110, 11001110, 01110110, 10110110, 11010110, 11100110, 01111010, 10111010, 11011010, 11101010, 11110010, 01111100, 10111100, 11011100, 11101100, 11110100, 11111000
|
||||
Level 5:
|
||||
00111111, 01011111, 10011111, 01101111, 10101111, 11001111, 01110111, 10110111, 11010111, 11100111, 01111011, 10111011, 11011011, 11101011, 11110011, 01111101, 10111101, 11011101, 11101101, 11110101, 11111001, 01111110, 10111110, 11011110, 11101110, 11110110, 11111010, 11111100
|
||||
Level 6:
|
||||
01111111, 10111111, 11011111, 11101111, 11110111, 11111011, 11111101, 11111110
|
||||
Level 7:
|
||||
11111111
|
||||
|
||||
Output plans (best plan 0):
|
||||
0.[11111111] HJ
|
||||
-> left:
|
||||
[10000000][test.nss7] COLLSCAN
|
||||
-> right:
|
||||
[01111111] INLJ
|
||||
-> left:
|
||||
[00111111] HJ
|
||||
-> left:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
-> right:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[01000000][test.nss6] INDEX_PROBE { a6: -1 }
|
||||
|
||||
1.[11111111] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[10111111] INLJ
|
||||
-> left:
|
||||
[00111111] HJ
|
||||
-> left:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
-> right:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
|
||||
2.[11111111] HJ
|
||||
-> left:
|
||||
[00100000][test.nss5] COLLSCAN
|
||||
-> right:
|
||||
[11011111] INLJ
|
||||
-> left:
|
||||
[01011111] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00011111] INLJ
|
||||
-> left:
|
||||
[00001111] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00010000][test.nss4] INDEX_PROBE { a4: -1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
|
||||
3.[11111111] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[11101111] INLJ
|
||||
-> left:
|
||||
[01101111] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00101111] INLJ
|
||||
-> left:
|
||||
[00001111] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
|
||||
4.[11111111] HJ
|
||||
-> left:
|
||||
[00001000][test.nss3] COLLSCAN
|
||||
-> right:
|
||||
[11110111] INLJ
|
||||
-> left:
|
||||
[01110111] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00110111] INLJ
|
||||
-> left:
|
||||
[00010111] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[00000111] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
|
||||
5.[11111111] HJ
|
||||
-> left:
|
||||
[00000100][test.nss2] COLLSCAN
|
||||
-> right:
|
||||
[11111011] INLJ
|
||||
-> left:
|
||||
[01111011] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00111011] INLJ
|
||||
-> left:
|
||||
[00011011] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[00001011] INLJ
|
||||
-> left:
|
||||
[00000011] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000010][test.nss1] INDEX_PROBE { a1: 1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
|
||||
6.[11111111] HJ
|
||||
-> left:
|
||||
[00000010][test.nss1] COLLSCAN
|
||||
-> right:
|
||||
[11111101] INLJ
|
||||
-> left:
|
||||
[01111101] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00111101] INLJ
|
||||
-> left:
|
||||
[00011101] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[00001101] INLJ
|
||||
-> left:
|
||||
[00000101] INLJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
|
||||
7.[11111111] HJ
|
||||
-> left:
|
||||
[00000001][test.nss0] COLLSCAN
|
||||
-> right:
|
||||
[11111110] INLJ
|
||||
-> left:
|
||||
[01111110] HJ
|
||||
-> left:
|
||||
[01000000][test.nss6] COLLSCAN
|
||||
-> right:
|
||||
[00111110] INLJ
|
||||
-> left:
|
||||
[00011110] HJ
|
||||
-> left:
|
||||
[00010000][test.nss4] COLLSCAN
|
||||
-> right:
|
||||
[00001110] INLJ
|
||||
-> left:
|
||||
[00000110] INLJ
|
||||
-> left:
|
||||
[00000010][test.nss1] COLLSCAN
|
||||
-> right:
|
||||
[00000100][test.nss2] INDEX_PROBE { a2: -1 }
|
||||
-> right:
|
||||
[00001000][test.nss3] INDEX_PROBE { a3: 1 }
|
||||
-> right:
|
||||
[00100000][test.nss5] INDEX_PROBE { a5: 1 }
|
||||
-> right:
|
||||
[10000000][test.nss7] INDEX_PROBE { a7: 1 }
|
||||
|
||||
Loading…
Reference in New Issue