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
|
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
|
## 2. Basic example with two joins and suffix
|
||||||
### No join opt
|
### No join opt
|
||||||
### Pipeline
|
### Pipeline
|
||||||
|
|
@ -1891,6 +1998,143 @@ Execution Engine: sbe
|
||||||
```
|
```
|
||||||
usedJoinOptimization: true
|
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
|
## 3. Basic example with referencing field from previous lookup
|
||||||
### No join opt
|
### No join opt
|
||||||
### Pipeline
|
### Pipeline
|
||||||
|
|
@ -2683,6 +2927,103 @@ Execution Engine: sbe
|
||||||
```
|
```
|
||||||
usedJoinOptimization: true
|
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
|
## 4. Basic example with 3 joins & subsequent join referencing fields from previous lookups
|
||||||
### No join opt
|
### No join opt
|
||||||
### Pipeline
|
### Pipeline
|
||||||
|
|
@ -3753,6 +4094,142 @@ Execution Engine: sbe
|
||||||
```
|
```
|
||||||
usedJoinOptimization: true
|
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
|
## 5. Basic example with 3 joins & subsequent join referencing nested paths
|
||||||
### No join opt
|
### No join opt
|
||||||
### Pipeline
|
### Pipeline
|
||||||
|
|
@ -4770,3 +5247,126 @@ Execution Engine: sbe
|
||||||
```
|
```
|
||||||
usedJoinOptimization: true
|
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*/);
|
outputAggregationPlanAndResults(coll, pipeline, {}, true, false, true /* noLineBreak*/);
|
||||||
const seed420HJResults = coll.aggregate(pipeline).toArray();
|
const seed420HJResults = coll.aggregate(pipeline).toArray();
|
||||||
verifyExplainOutput(pipeline, true /* joinOptExpectedInExplainOutput */);
|
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}));
|
assert.commandWorked(db.adminCommand({setParameter: 1, internalRandomJoinReorderDefaultToHashJoin: false}));
|
||||||
|
|
||||||
foreignColl1.createIndex({a: 1});
|
foreignColl1.createIndex({a: 1});
|
||||||
foreignColl2.createIndex({b: 1});
|
foreignColl2.createIndex({b: 1});
|
||||||
subSection("With fixed order, index join");
|
subSection("With fixed order, index join");
|
||||||
|
|
||||||
outputAggregationPlanAndResults(coll, pipeline, {}, true, false, true /* noLineBreak*/);
|
outputAggregationPlanAndResults(coll, pipeline, {}, true, false, true /* noLineBreak*/);
|
||||||
const seedINJResults = coll.aggregate(pipeline).toArray();
|
|
||||||
verifyExplainOutput(pipeline, true /* joinOptExpectedInExplainOutput */);
|
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});
|
foreignColl1.dropIndex({a: 1});
|
||||||
foreignColl2.dropIndex({b: 1});
|
foreignColl2.dropIndex({b: 1});
|
||||||
assert(
|
|
||||||
_resultSetsEqualUnordered(noJoinOptResults, seedINJResults),
|
|
||||||
"Results differ between no join opt and INJ",
|
|
||||||
);
|
|
||||||
} finally {
|
} finally {
|
||||||
// Reset flags.
|
// Reset flags.
|
||||||
assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: false}));
|
assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: false}));
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ bool isAggEligibleForJoinReordering(const MultipleCollectionAccessor& mca,
|
||||||
return AggJoinModel::pipelineEligibleForJoinReordering(pipeline);
|
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();
|
auto desc = ice->descriptor();
|
||||||
return !desc->isHashedIdIndex() && !desc->hidden() && !desc->isPartial() && !desc->isSparse() &&
|
return !desc->isHashedIdIndex() && !desc->hidden() && !desc->isPartial() && !desc->isSparse() &&
|
||||||
desc->collation().isEmpty() && !dynamic_cast<WildcardAccessMethod*>(ice->accessMethod());
|
desc->collation().isEmpty() && !dynamic_cast<WildcardAccessMethod*>(ice->accessMethod());
|
||||||
|
|
@ -121,8 +121,7 @@ AvailableIndexes extractINLJEligibleIndexes(const QuerySolutionMap& solns,
|
||||||
AvailableIndexes perCollIdxs;
|
AvailableIndexes perCollIdxs;
|
||||||
for (const auto& [cq, _] : solns) {
|
for (const auto& [cq, _] : solns) {
|
||||||
const auto& ns = cq->nss();
|
const auto& ns = cq->nss();
|
||||||
auto it = perCollIdxs.find(ns);
|
if (perCollIdxs.contains(ns)) {
|
||||||
if (it != perCollIdxs.end()) {
|
|
||||||
// We've already pre-processed this collection's indexes.
|
// We've already pre-processed this collection's indexes.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,21 @@
|
||||||
|
|
||||||
#include "mongo/bson/bsonobjbuilder.h"
|
#include "mongo/bson/bsonobjbuilder.h"
|
||||||
#include "mongo/db/query/compiler/optimizer/join/join_graph.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"
|
#include "mongo/util/str.h"
|
||||||
|
|
||||||
namespace mongo::join_ordering {
|
namespace mongo::join_ordering {
|
||||||
namespace {
|
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.
|
* Helper to pretty-print NodeSet.
|
||||||
*/
|
*/
|
||||||
|
|
@ -57,20 +68,29 @@ std::string joinMethodToString(JoinMethod method) {
|
||||||
|
|
||||||
MONGO_UNREACHABLE_TASSERT(11336901);
|
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
|
} // namespace
|
||||||
|
|
||||||
std::string BaseNode::toString(size_t numNodesToPrint, std::string indentStr) const {
|
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();
|
<< nss.toString_forTest() << "] " << soln->summaryString();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string JoiningNode::toString(size_t numNodesToPrint, std::string indentStr) const {
|
std::string INLJRHSNode::toString(size_t numNodesToPrint, std::string indentStr) const {
|
||||||
auto ss = std::stringstream() << indentStr << "[" << nodeSetToString(bitset, numNodesToPrint)
|
return str::stream() << joinNodeStringPrefix(*this, numNodesToPrint, indentStr) << "["
|
||||||
<< "] ";
|
<< nss.toString_forTest() << "] INDEX_PROBE "
|
||||||
const auto methodStr = joinMethodToString(method);
|
<< entry->descriptor()->keyPattern();
|
||||||
|
}
|
||||||
|
|
||||||
ss << methodStr;
|
std::string JoiningNode::toString(size_t numNodesToPrint, std::string indentStr) const {
|
||||||
return ss.str();
|
return str::stream() << joinNodeStringPrefix(*this, numNodesToPrint, indentStr) << " "
|
||||||
|
<< joinMethodToString(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string JoinSubset::toString(size_t numNodesToPrint) const {
|
std::string JoinSubset::toString(size_t numNodesToPrint) const {
|
||||||
|
|
@ -91,11 +111,19 @@ JoinPlanNodeId JoinPlanNodeRegistry::registerJoinNode(const JoinSubset& subset,
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
JoinPlanNodeId JoinPlanNodeRegistry::registerBaseNode(const JoinSubset& subset,
|
JoinPlanNodeId JoinPlanNodeRegistry::registerBaseNode(NodeId node,
|
||||||
const QuerySolution* soln,
|
const QuerySolution* soln,
|
||||||
const NamespaceString& nss) {
|
const NamespaceString& nss) {
|
||||||
|
tassert(11371702, "Expected an initialized qsn", soln);
|
||||||
JoinPlanNodeId id = _allJoinPlans.size();
|
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;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,6 +136,9 @@ std::string JoinPlanNodeRegistry::joinPlanNodeToString(JoinPlanNodeId nodeId,
|
||||||
[&indentStr, &ss, numNodesToPrint](const BaseNode& n) {
|
[&indentStr, &ss, numNodesToPrint](const BaseNode& n) {
|
||||||
ss << n.toString(numNodesToPrint, indentStr);
|
ss << n.toString(numNodesToPrint, indentStr);
|
||||||
},
|
},
|
||||||
|
[&indentStr, &ss, numNodesToPrint](const INLJRHSNode& n) {
|
||||||
|
ss << n.toString(numNodesToPrint, indentStr);
|
||||||
|
},
|
||||||
[this, &indentStr, &ss, numNodesToPrint](const JoiningNode& n) {
|
[this, &indentStr, &ss, numNodesToPrint](const JoiningNode& n) {
|
||||||
std::string nxtIndent = str::stream() << indentStr + " ";
|
std::string nxtIndent = str::stream() << indentStr + " ";
|
||||||
ss << n.toString(numNodesToPrint, indentStr) << "\n"
|
ss << n.toString(numNodesToPrint, indentStr) << "\n"
|
||||||
|
|
@ -135,24 +166,34 @@ std::string JoinPlanNodeRegistry::joinPlansToString(const JoinPlans& plans,
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeSet JoinPlanNodeRegistry::getBitset(JoinPlanNodeId id) const {
|
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,
|
BSONObj JoinPlanNodeRegistry::joinPlanNodeToBSON(JoinPlanNodeId nodeId,
|
||||||
size_t numNodesToPrint) const {
|
size_t numNodesToPrint) const {
|
||||||
return std::visit(
|
return std::visit(
|
||||||
OverloadedVisitor{[this, numNodesToPrint](const JoiningNode& join) {
|
OverloadedVisitor{
|
||||||
return BSON("subset"
|
[this, numNodesToPrint](const JoiningNode& join) {
|
||||||
<< nodeSetToString(join.bitset, numNodesToPrint)
|
return BSON("subset" << nodeSetToString(join.bitset, numNodesToPrint) << "method"
|
||||||
<< "method" << joinMethodToString(join.method) << "left"
|
<< joinMethodToString(join.method) << "left"
|
||||||
<< joinPlanNodeToBSON(join.left, numNodesToPrint)
|
<< joinPlanNodeToBSON(join.left, numNodesToPrint) << "right"
|
||||||
<< "right"
|
<< joinPlanNodeToBSON(join.right, numNodesToPrint));
|
||||||
<< joinPlanNodeToBSON(join.right, numNodesToPrint));
|
},
|
||||||
},
|
[numNodesToPrint](const INLJRHSNode& ip) {
|
||||||
[numNodesToPrint](const BaseNode& base) {
|
return BSON("subset" << nodeSetToString(ip.node, numNodesToPrint) << "accessPath"
|
||||||
return BSON("subset" << nodeSetToString(base.bitset, numNodesToPrint)
|
<< (str::stream() << "INDEX_PROBE "
|
||||||
<< "accessPath" << base.soln->summaryString());
|
<< ip.entry->descriptor()->keyPattern()));
|
||||||
}},
|
},
|
||||||
|
[numNodesToPrint](const BaseNode& base) {
|
||||||
|
return BSON("subset" << nodeSetToString(base.node, numNodesToPrint) << "accessPath"
|
||||||
|
<< base.soln->summaryString());
|
||||||
|
}},
|
||||||
get(nodeId));
|
get(nodeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include "mongo/db/namespace_string.h"
|
#include "mongo/db/namespace_string.h"
|
||||||
#include "mongo/db/query/compiler/optimizer/join/join_graph.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/compiler/physical_model/query_solution/query_solution.h"
|
||||||
|
#include "mongo/db/query/util/bitset_util.h"
|
||||||
#include "mongo/util/modules.h"
|
#include "mongo/util/modules.h"
|
||||||
|
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
@ -40,9 +41,10 @@ namespace mongo::join_ordering {
|
||||||
// Forward declarations.
|
// Forward declarations.
|
||||||
struct JoiningNode;
|
struct JoiningNode;
|
||||||
struct BaseNode;
|
struct BaseNode;
|
||||||
|
struct INLJRHSNode;
|
||||||
|
|
||||||
using JoinPlanNodeId = size_t;
|
using JoinPlanNodeId = size_t;
|
||||||
using JoinPlanNode = std::variant<JoiningNode, BaseNode>;
|
using JoinPlanNode = std::variant<JoiningNode, BaseNode, INLJRHSNode>;
|
||||||
using JoinPlans = std::vector<JoinPlanNodeId>;
|
using JoinPlans = std::vector<JoinPlanNodeId>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -64,6 +66,11 @@ struct JoinSubset {
|
||||||
return subset.count() == 1;
|
return subset.count() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeId getNodeId() const {
|
||||||
|
tassert(11371703, "Must have just one node", isBaseCollectionAccess());
|
||||||
|
return (NodeId)*begin(subset);
|
||||||
|
}
|
||||||
|
|
||||||
inline JoinPlanNodeId bestPlan() const {
|
inline JoinPlanNodeId bestPlan() const {
|
||||||
tassert(11336908, "Expected bestPlanIndex < plans.size()", bestPlanIndex < plans.size());
|
tassert(11336908, "Expected bestPlanIndex < plans.size()", bestPlanIndex < plans.size());
|
||||||
return plans[bestPlanIndex];
|
return plans[bestPlanIndex];
|
||||||
|
|
@ -99,11 +106,29 @@ enum class JoinMethod {
|
||||||
struct BaseNode {
|
struct BaseNode {
|
||||||
// Pointer to best access path obtained by CBR.
|
// Pointer to best access path obtained by CBR.
|
||||||
const QuerySolution* soln;
|
const QuerySolution* soln;
|
||||||
|
|
||||||
// Namespace this access path corresponds to.
|
// Namespace this access path corresponds to.
|
||||||
const NamespaceString& nss;
|
const NamespaceString& nss;
|
||||||
|
|
||||||
// Keeps a copy of the bitset representing the subgraph this originated from.
|
// Corresponds to node in the graph this represents a base table access to.
|
||||||
const NodeSet bitset;
|
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 toString(size_t numNodesToPrint = kMaxNodesInJoin,
|
||||||
std::string indentStr = "") const;
|
std::string indentStr = "") const;
|
||||||
|
|
@ -146,9 +171,12 @@ public:
|
||||||
JoinMethod method,
|
JoinMethod method,
|
||||||
JoinPlanNodeId left,
|
JoinPlanNodeId left,
|
||||||
JoinPlanNodeId right);
|
JoinPlanNodeId right);
|
||||||
JoinPlanNodeId registerBaseNode(const JoinSubset& subset,
|
JoinPlanNodeId registerBaseNode(NodeId node,
|
||||||
const QuerySolution* soln,
|
const QuerySolution* soln,
|
||||||
const NamespaceString& nss);
|
const NamespaceString& nss);
|
||||||
|
JoinPlanNodeId registerINLJRHSNode(NodeId node,
|
||||||
|
std::shared_ptr<const IndexCatalogEntry> entry,
|
||||||
|
const NamespaceString& nss);
|
||||||
|
|
||||||
const JoinPlanNode& get(JoinPlanNodeId id) const {
|
const JoinPlanNode& get(JoinPlanNodeId id) const {
|
||||||
return _allJoinPlans[id];
|
return _allJoinPlans[id];
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,6 @@
|
||||||
#include "mongo/db/query/compiler/optimizer/join/plan_enumerator_helpers.h"
|
#include "mongo/db/query/compiler/optimizer/join/plan_enumerator_helpers.h"
|
||||||
#include "mongo/logv2/log.h"
|
#include "mongo/logv2/log.h"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery
|
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery
|
||||||
|
|
||||||
namespace mongo::join_ordering {
|
namespace mongo::join_ordering {
|
||||||
|
|
@ -52,9 +50,10 @@ bool PlanEnumeratorContext::canPlanBeEnumerated(PlanTreeShape type,
|
||||||
const JoinSubset& left,
|
const JoinSubset& left,
|
||||||
const JoinSubset& right,
|
const JoinSubset& right,
|
||||||
const JoinSubset& subset) const {
|
const JoinSubset& subset) const {
|
||||||
if (method == JoinMethod::NLJ && !right.isBaseCollectionAccess()) {
|
if ((method == JoinMethod::NLJ || method == JoinMethod::INLJ) &&
|
||||||
// NLJ plans perform poorly when the right hand side is not a collection access- don't
|
!right.isBaseCollectionAccess()) {
|
||||||
// enumerate this plan.
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,8 +102,8 @@ bool PlanEnumeratorContext::canPlanBeEnumerated(PlanTreeShape type,
|
||||||
*/
|
*/
|
||||||
const auto& leftJoin = _registry.getAs<JoiningNode>(left.bestPlan());
|
const auto& leftJoin = _registry.getAs<JoiningNode>(left.bestPlan());
|
||||||
return _registry.isOfType<JoiningNode>(leftJoin.right) ||
|
return _registry.isOfType<JoiningNode>(leftJoin.right) ||
|
||||||
(_registry.isOfType<BaseNode>(leftJoin.right) &&
|
(!_registry.isOfType<JoiningNode>(leftJoin.right) &&
|
||||||
_registry.isOfType<BaseNode>(leftJoin.left));
|
!_registry.isOfType<JoiningNode>(leftJoin.left));
|
||||||
|
|
||||||
} else if (!right.isBaseCollectionAccess()) {
|
} else if (!right.isBaseCollectionAccess()) {
|
||||||
/**
|
/**
|
||||||
|
|
@ -126,8 +125,8 @@ bool PlanEnumeratorContext::canPlanBeEnumerated(PlanTreeShape type,
|
||||||
*/
|
*/
|
||||||
const auto& rightJoin = _registry.getAs<JoiningNode>(right.bestPlan());
|
const auto& rightJoin = _registry.getAs<JoiningNode>(right.bestPlan());
|
||||||
return _registry.isOfType<JoiningNode>(rightJoin.left) ||
|
return _registry.isOfType<JoiningNode>(rightJoin.left) ||
|
||||||
(_registry.isOfType<BaseNode>(rightJoin.right) &&
|
(!_registry.isOfType<JoiningNode>(rightJoin.right) &&
|
||||||
_registry.isOfType<BaseNode>(rightJoin.left));
|
!_registry.isOfType<JoiningNode>(rightJoin.left));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -147,9 +146,27 @@ void PlanEnumeratorContext::addJoinPlan(PlanTreeShape type,
|
||||||
if (!canPlanBeEnumerated(type, method, left, right, subset)) {
|
if (!canPlanBeEnumerated(type, method, left, right, subset)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO SERVER-113059: Rudimentary cost metric/tracking.
|
|
||||||
subset.plans.push_back(
|
if (method == JoinMethod::INLJ) {
|
||||||
_registry.registerJoinNode(subset, method, left.bestPlan(), right.bestPlan()));
|
// 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,
|
LOGV2_DEBUG(11336912,
|
||||||
5,
|
5,
|
||||||
|
|
@ -179,6 +196,7 @@ void PlanEnumeratorContext::enumerateJoinPlans(PlanTreeShape type,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addJoinPlan(type, JoinMethod::INLJ, left, right, joinEdges, cur);
|
||||||
addJoinPlan(type, JoinMethod::HJ, left, right, joinEdges, cur);
|
addJoinPlan(type, JoinMethod::HJ, left, right, joinEdges, cur);
|
||||||
addJoinPlan(type, JoinMethod::NLJ, 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();
|
const auto* qsn = _ctx.cbrCqQsns.at(cq).get();
|
||||||
_joinSubsets[kBaseLevel].push_back(JoinSubset(NodeSet{}.set(i)));
|
_joinSubsets[kBaseLevel].push_back(JoinSubset(NodeSet{}.set(i)));
|
||||||
_joinSubsets[kBaseLevel].back().plans = {
|
_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.
|
// Initialize the rest of the joinSubsets.
|
||||||
for (int level = 1; level < numNodes; ++level) {
|
for (int level = 1; level < numNodes; ++level) {
|
||||||
const auto& joinSubsetsPrevLevel = _joinSubsets[level - 1];
|
auto& joinSubsetsPrevLevel = _joinSubsets[level - 1];
|
||||||
auto& joinSubsetsCurrLevel = _joinSubsets[level];
|
auto& joinSubsetsCurrLevel = _joinSubsets[level];
|
||||||
// Preallocate entries for all subsets in the current level.
|
// Preallocate entries for all subsets in the current level.
|
||||||
joinSubsetsCurrLevel.reserve(cs.next());
|
joinSubsetsCurrLevel.reserve(cs.next());
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ DEATH_TEST(PlanEnumeratorHelpersDeathTest, TooManyInvocationsOfCombinationSequen
|
||||||
|
|
||||||
class JoinPlanEnumeratorTest : public JoinOrderingTestFixture {
|
class JoinPlanEnumeratorTest : public JoinOrderingTestFixture {
|
||||||
public:
|
public:
|
||||||
void initGraph(size_t numNodes) {
|
void initGraph(size_t numNodes, bool withIndexes = false) {
|
||||||
for (size_t i = 0; i < numNodes; i++) {
|
for (size_t i = 0; i < numNodes; i++) {
|
||||||
auto nss =
|
auto nss =
|
||||||
NamespaceString::createNamespaceString_forTest("test", str::stream() << "nss" << i);
|
NamespaceString::createNamespaceString_forTest("test", str::stream() << "nss" << i);
|
||||||
|
|
@ -95,19 +95,27 @@ public:
|
||||||
jCtx.cbrCqQsns.insert(
|
jCtx.cbrCqQsns.insert(
|
||||||
{cq.get(), makeCollScanPlan(nss, cq->getPrimaryMatchExpression()->clone())});
|
{cq.get(), makeCollScanPlan(nss, cq->getPrimaryMatchExpression()->clone())});
|
||||||
ASSERT_TRUE(graph.addNode(nss, std::move(cq), boost::none).has_value());
|
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,
|
void testLargeSubset(unittest::GoldenTestContext* goldenCtx,
|
||||||
PlanTreeShape shape,
|
PlanTreeShape shape,
|
||||||
size_t numNodes) {
|
size_t numNodes,
|
||||||
initGraph(numNodes);
|
bool withIndexes = false) {
|
||||||
|
initGraph(numNodes, withIndexes);
|
||||||
|
|
||||||
for (size_t i = 1; i < numNodes; ++i) {
|
for (size_t i = 1; i < numNodes; ++i) {
|
||||||
// Make the graph fully connected in order to ensure we generate as many plans as
|
// Make the graph fully connected in order to ensure we generate as many plans as
|
||||||
// possible.
|
// possible.
|
||||||
for (size_t j = 0; j < i; ++j) {
|
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);
|
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) {
|
TEST_F(JoinPlanEnumeratorTest, RightDeep8Nodes) {
|
||||||
unittest::GoldenTestContext goldenCtx(&goldenTestConfig);
|
unittest::GoldenTestContext goldenCtx(&goldenTestConfig);
|
||||||
testLargeSubset(&goldenCtx, PlanTreeShape::RIGHT_DEEP, 8);
|
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) {
|
TEST_F(JoinPlanEnumeratorTest, ZigZag8Nodes) {
|
||||||
unittest::GoldenTestContext goldenCtx(&goldenTestConfig);
|
unittest::GoldenTestContext goldenCtx(&goldenTestConfig);
|
||||||
testLargeSubset(&goldenCtx, PlanTreeShape::ZIG_ZAG, 8);
|
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) {
|
TEST_F(JoinPlanEnumeratorTest, InitialzeLargeSubsets) {
|
||||||
testLargeSubset(nullptr /* No golden test here. */, PlanTreeShape::LEFT_DEEP, 15);
|
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/reorder_joins.h"
|
||||||
|
|
||||||
#include "mongo/db/query/compiler/optimizer/join/join_graph.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/join_reordering_context.h"
|
||||||
#include "mongo/db/query/compiler/optimizer/join/plan_enumerator.h"
|
#include "mongo/db/query/compiler/optimizer/join/plan_enumerator.h"
|
||||||
#include "mongo/db/query/compiler/optimizer/join/plan_enumerator_helpers.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) {
|
[&qsn](const BaseNode& base) {
|
||||||
// TODO SERVER-111913: Avoid this clone
|
// TODO SERVER-111913: Avoid this clone
|
||||||
qsn = base.soln->root()->clone();
|
qsn = base.soln->root()->clone();
|
||||||
|
},
|
||||||
|
[&ctx, &qsn, ®istry](const INLJRHSNode& ip) {
|
||||||
|
qsn = createIndexProbeQSN(ctx.joinGraph.getNode(ip.node),
|
||||||
|
ip.entry);
|
||||||
}},
|
}},
|
||||||
registry.get(nodeId));
|
registry.get(nodeId));
|
||||||
return qsn;
|
return qsn;
|
||||||
|
|
@ -187,9 +192,11 @@ NodeId getLeftmostNodeIdOfJoinPlan(const JoinReorderingContext& ctx,
|
||||||
return getLeftmostNodeIdOfJoinPlan(
|
return getLeftmostNodeIdOfJoinPlan(
|
||||||
ctx, join.left, registry);
|
ctx, join.left, registry);
|
||||||
},
|
},
|
||||||
[](const BaseNode& base) {
|
[](const BaseNode& base) { return base.node; },
|
||||||
BitsetIterator<kMaxNodesInJoin> it = begin(base.bitset);
|
[](const INLJRHSNode&) {
|
||||||
return (NodeId)*it;
|
// By definition, this should never happen.
|
||||||
|
MONGO_UNREACHABLE_TASSERT(11371704);
|
||||||
|
return (NodeId)0;
|
||||||
}},
|
}},
|
||||||
registry.get(nodeId));
|
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/join_reordering_context.h"
|
||||||
#include "mongo/db/query/compiler/optimizer/join/plan_enumerator_helpers.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/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/golden_test.h"
|
||||||
#include "mongo/unittest/unittest.h"
|
#include "mongo/unittest/unittest.h"
|
||||||
|
|
||||||
|
|
@ -55,36 +52,6 @@ QuerySolutionMap cloneSolnMap(const QuerySolutionMap& qsm) {
|
||||||
return ret;
|
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 {
|
class ReorderGraphTest : public JoinOrderingTestFixture {
|
||||||
protected:
|
protected:
|
||||||
// Helper struct for intializing a namespace, its embedding, any residual filter, and indexes
|
// 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;
|
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,
|
MultipleCollectionAccessor multipleCollectionAccessor(OperationContext* opCtx,
|
||||||
std::vector<NamespaceString> namespaces) {
|
std::vector<NamespaceString> namespaces) {
|
||||||
auto mainAcquisitionReq = CollectionAcquisitionRequest::fromOpCtx(
|
auto mainAcquisitionReq = CollectionAcquisitionRequest::fromOpCtx(
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,9 @@
|
||||||
#include "mongo/db/query/compiler/optimizer/join/join_reordering_context.h"
|
#include "mongo/db/query/compiler/optimizer/join/join_reordering_context.h"
|
||||||
#include "mongo/db/query/multiple_collection_accessor.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/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/unittest/golden_test_base.h"
|
||||||
#include "mongo/util/modules.h"
|
#include "mongo/util/modules.h"
|
||||||
|
|
||||||
|
|
@ -46,6 +49,16 @@ namespace mongo::join_ordering {
|
||||||
MultipleCollectionAccessor multipleCollectionAccessor(OperationContext* opCtx,
|
MultipleCollectionAccessor multipleCollectionAccessor(OperationContext* opCtx,
|
||||||
std::vector<NamespaceString> namespaces);
|
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
|
* Text fixture with helpful functions for manipulating the catalog, constructing samples and
|
||||||
* queries/QSNs.
|
* 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