diff options
author | David Storch <david.storch@10gen.com> | 2015-05-29 19:15:19 -0400 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2015-07-10 17:11:16 -0400 |
commit | 15c72c8570c63e2e6ba0a3d339a8286d0be604db (patch) | |
tree | 96cc37b3259e9ce7472132b8c414eb614317c037 /src/mongo/db/query/query_planner_test.cpp | |
parent | 9c63b79a8d5c8d19663850f9d668a3581dea77d5 (diff) | |
download | mongo-15c72c8570c63e2e6ba0a3d339a8286d0be604db.tar.gz |
SERVER-13732 rewrite contained $or queries to rooted $or in the SubplanStage
This allows queries with an $or contained within an explicit or implicit $and to be answered with
more efficient plans. It also expands the use of the SubplanStage to include contained $or queries
and therefore may reduce the number of plans considered for these queries.
Diffstat (limited to 'src/mongo/db/query/query_planner_test.cpp')
-rw-r--r-- | src/mongo/db/query/query_planner_test.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp index 4768eed4312..9950b295cc1 100644 --- a/src/mongo/db/query/query_planner_test.cpp +++ b/src/mongo/db/query/query_planner_test.cpp @@ -706,6 +706,128 @@ TEST_F(QueryPlannerTest, OrOfAnd6) { " b: [[1,1,true,true], [5,5,true,true]]}}}]}}}}"); } +// We do collapse OR of ANDs if branches of the OR plan are using identical index scans. +TEST_F(QueryPlannerTest, RootedOrOfAndCollapseIndenticalScans) { + addIndex(BSON("a" << 1 << "b" << 1)); + runQuery(fromjson("{$or: [{a:1, b:2}, {a:1, b:2}]}")); + + assertNumSolutions(2U); + assertSolutionExists("{cscan: {dir: 1}}"); + assertSolutionExists( + "{fetch: {filter: null, node: {ixscan: {pattern: {a: 1, b: 1}}," + "bounds: {a: [[1,1,true,true]], b: [[2,2,true,true]]}," + "filter: null}}}"); +} + +TEST_F(QueryPlannerTest, ContainedOrOfAndCollapseIndenticalScans) { + addIndex(BSON("a" << 1 << "b" << 1)); + runQuery(fromjson("{c: 1, $or: [{a:1, b:2}, {a:1, b:2}]}")); + + assertNumSolutions(2U); + assertSolutionExists("{cscan: {dir: 1}}"); + assertSolutionExists( + "{fetch: {filter: {c: 1}, node: {ixscan: {pattern: {a: 1, b: 1}}," + "bounds: {a: [[1,1,true,true]], b: [[2,2,true,true]]}," + "filter: null}}}"); +} + +TEST_F(QueryPlannerTest, ContainedOrOfAndCollapseIndenticalScansWithFilter) { + addIndex(BSON("a" << 1 << "b" << 1)); + runQuery(fromjson("{c: 1, $or: [{a:1, b:2}, {a:1, b:2, d:3}]}")); + + assertNumSolutions(2U); + assertSolutionExists("{cscan: {dir: 1}}"); + assertSolutionExists( + "{fetch: {filter: {c: 1}, node: {ixscan: {pattern: {a: 1, b: 1}}," + "bounds: {a: [[1,1,true,true]], b: [[2,2,true,true]]}," + "filter: null}}}"); +} + +TEST_F(QueryPlannerTest, ContainedOrOfAndCollapseIndenticalScansWithFilter2) { + addIndex(BSON("a" << 1 << "b" << 1)); + runQuery(fromjson("{c: 1, $or: [{a:{$gte:1,$lte:1}, b:2}, {a:1, b:2, d:3}]}")); + + assertNumSolutions(2U); + assertSolutionExists("{cscan: {dir: 1}}"); + assertSolutionExists( + "{fetch: {filter: {c: 1}, node: {fetch: {filter: null, node: " + "{ixscan: {pattern: {a: 1, b: 1}}," + "bounds: {a: [[1,1,true,true]], b: [[2,2,true,true]]}," + "filter: null}}}}}"); +} + +TEST_F(QueryPlannerTest, ContainedOrOfAndCollapseIdenticalScansTwoFilters) { + addIndex(BSON("a" << 1 << "b" << 1)); + runQuery(fromjson("{c: 1, $or: [{a:1, b:2, d:3}, {a:1, b:2, e:4}]}")); + + assertNumSolutions(2U); + assertSolutionExists("{cscan: {dir: 1}}"); + assertSolutionExists( + "{fetch: {filter: {c: 1}, node: {fetch: {filter: {$or:[{e:4},{d:3}]}," + "node: {ixscan: {pattern: {a: 1, b: 1}, filter: null," + "bounds: {a: [[1,1,true,true]], b: [[2,2,true,true]]}}}}}}}"); +} + +TEST_F(QueryPlannerTest, RootedOrOfAndCollapseScansExistingOrFilter) { + addIndex(BSON("a" << 1 << "b" << 1)); + runQuery(fromjson("{$or: [{a:1, b:2, $or: [{c:3}, {d:4}]}, {a:1, b:2, e:5}]}")); + + assertNumSolutions(2U); + assertSolutionExists("{cscan: {dir: 1}}"); + assertSolutionExists( + "{fetch: {filter: {$or: [{e:5},{c:3},{d:4}]}, node: {ixscan: " + "{filter: null, pattern: {a: 1, b: 1}, " + "bounds: {a: [[1,1,true,true]], b: [[2,2,true,true]]}}}}}"); +} + +TEST_F(QueryPlannerTest, RootedOrOfAndCollapseTwoScansButNotThird) { + addIndex(BSON("a" << 1 << "b" << 1)); + addIndex(BSON("c" << 1 << "d" << 1)); + runQuery(fromjson("{$or: [{a: 1, b: 2}, {c: 3, d: 4}, {a: 1, b: 2}]}")); + + assertNumSolutions(2U); + assertSolutionExists("{cscan: {dir: 1}}"); + assertSolutionExists( + "{fetch: {filter: null, node: {or: {nodes: [" + "{ixscan: {pattern: {a: 1, b: 1}, filter: null," + "bounds: {a: [[1,1,true,true]], b: [[2,2,true,true]]}}}," + "{ixscan: {pattern: {c: 1, d: 1}, filter: null," + "bounds: {c: [[3,3,true,true]], d: [[4,4,true,true]]}}}]}}}}"); +} + +TEST_F(QueryPlannerTest, RootedOrOfAndCollapseTwoScansButNotThirdWithFilters) { + addIndex(BSON("a" << 1 << "b" << 1)); + addIndex(BSON("c" << 1 << "d" << 1)); + runQuery(fromjson("{$or: [{a:1, b:2, e:5}, {c:3, d:4}, {a:1, b:2, f:6}]}")); + + assertNumSolutions(2U); + assertSolutionExists("{cscan: {dir: 1}}"); + assertSolutionExists( + "{fetch: {filter: null, node: {or: {nodes: [" + "{fetch: {filter: {$or: [{f:6},{e:5}]}, node: " + "{ixscan: {pattern: {a: 1, b: 1}, filter: null," + "bounds: {a: [[1,1,true,true]], b: [[2,2,true,true]]}}}}}," + "{ixscan: {pattern: {c: 1, d: 1}, filter: null," + "bounds: {c: [[3,3,true,true]], d: [[4,4,true,true]]}}}]}}}}"); +} + +TEST_F(QueryPlannerTest, RootedOrOfAndDontCollapseDifferentBounds) { + addIndex(BSON("a" << 1 << "b" << 1)); + addIndex(BSON("c" << 1 << "d" << 1)); + runQuery(fromjson("{$or: [{a: 1, b: 2}, {c: 3, d: 4}, {a: 1, b: 99}]}")); + + assertNumSolutions(2U); + assertSolutionExists("{cscan: {dir: 1}}"); + assertSolutionExists( + "{fetch: {filter: null, node: {or: {nodes: [" + "{ixscan: {pattern: {a: 1, b: 1}, filter: null," + "bounds: {a: [[1,1,true,true]], b: [[2,2,true,true]]}}}," + "{ixscan: {pattern: {a: 1, b: 1}, filter: null," + "bounds: {a: [[1,1,true,true]], b: [[99,99,true,true]]}}}," + "{ixscan: {pattern: {c: 1, d: 1}, filter: null," + "bounds: {c: [[3,3,true,true]], d: [[4,4,true,true]]}}}]}}}}"); +} + // SERVER-13960: properly handle $or with a mix of exact and inexact predicates. TEST_F(QueryPlannerTest, OrInexactWithExact) { addIndex(BSON("name" << 1)); |