diff options
author | David Storch <david.storch@10gen.com> | 2014-09-17 09:38:54 -0400 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2014-09-17 09:38:54 -0400 |
commit | 8baf068f5c7bcb52c7cc19bd6343fc2569cd92fc (patch) | |
tree | 88c193cad7e3fd741f1ace817958055251aa8dde /src/mongo/db | |
parent | 47260bcc495c093e5a2542a3d2ccdd43e796a369 (diff) | |
download | mongo-8baf068f5c7bcb52c7cc19bd6343fc2569cd92fc.tar.gz |
SERVER-15279 disable hash-based index intersection by default
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/query/planner_access.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/query/query_knobs.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/query/query_knobs.h | 3 | ||||
-rw-r--r-- | src/mongo/db/query/query_planner_test.cpp | 31 |
4 files changed, 49 insertions, 1 deletions
diff --git a/src/mongo/db/query/planner_access.cpp b/src/mongo/db/query/planner_access.cpp index b5f38a61626..ee514ddb187 100644 --- a/src/mongo/db/query/planner_access.cpp +++ b/src/mongo/db/query/planner_access.cpp @@ -38,6 +38,7 @@ #include "mongo/db/query/index_bounds_builder.h" #include "mongo/db/query/index_tag.h" #include "mongo/db/query/qlog.h" +#include "mongo/db/query/query_knobs.h" #include "mongo/db/query/query_planner.h" #include "mongo/db/query/query_planner_common.h" #include "mongo/util/log.h" @@ -871,7 +872,7 @@ namespace mongo { asn->children.swap(ixscanNodes); andResult = asn; } - else { + else if (internalQueryPlannerEnableHashIntersection) { AndHashNode* ahn = new AndHashNode(); ahn->children.swap(ixscanNodes); andResult = ahn; @@ -887,6 +888,17 @@ namespace mongo { } } } + else { + // We can't use sort-based intersection, and hash-based intersection is disabled. + // Clean up the index scans and bail out by returning NULL. + QLOG() << "Can't build index intersection solution: " + << "AND_SORTED is not possible and AND_HASH is disabled."; + + for (size_t i = 0; i < ixscanNodes.size(); i++) { + delete ixscanNodes[i]; + } + return NULL; + } } // Don't bother doing any kind of fetch analysis lite if we're doing it anyway above us. diff --git a/src/mongo/db/query/query_knobs.cpp b/src/mongo/db/query/query_knobs.cpp index 6b0503a4578..30efd8d15e9 100644 --- a/src/mongo/db/query/query_knobs.cpp +++ b/src/mongo/db/query/query_knobs.cpp @@ -56,6 +56,8 @@ namespace mongo { MONGO_EXPORT_SERVER_PARAMETER(internalQueryPlannerEnableIndexIntersection, bool, true); + MONGO_EXPORT_SERVER_PARAMETER(internalQueryPlannerEnableHashIntersection, bool, false); + MONGO_EXPORT_SERVER_PARAMETER(internalQueryPlanOrChildrenIndependently, bool, true); MONGO_EXPORT_SERVER_PARAMETER(internalQueryMaxScansToExplode, int, 200); diff --git a/src/mongo/db/query/query_knobs.h b/src/mongo/db/query/query_knobs.h index d12858264c7..913362558d7 100644 --- a/src/mongo/db/query/query_knobs.h +++ b/src/mongo/db/query/query_knobs.h @@ -51,6 +51,9 @@ namespace mongo { // Do we have ixisect on at all? extern bool internalQueryPlannerEnableIndexIntersection; + // Do we use hash-based intersection for rooted $and queries? + extern bool internalQueryPlannerEnableHashIntersection; + // // plan cache // diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp index d6164250285..b329c0378b7 100644 --- a/src/mongo/db/query/query_planner_test.cpp +++ b/src/mongo/db/query/query_planner_test.cpp @@ -53,6 +53,7 @@ namespace { class QueryPlannerTest : public mongo::unittest::Test { protected: void setUp() { + internalQueryPlannerEnableHashIntersection = true; params.options = QueryPlannerParams::INCLUDE_COLLSCAN; addIndex(BSON("_id" << 1)); } @@ -4411,6 +4412,36 @@ namespace { assertNumSolutions(internalQueryEnumerationMaxOrSolutions); } + // Ensure that disabling AND_HASH intersection works properly. + TEST_F(QueryPlannerTest, IntersectDisableAndHash) { + bool oldEnableHashIntersection = internalQueryPlannerEnableHashIntersection; + + // Turn index intersection on but disable hash-based intersection. + internalQueryPlannerEnableHashIntersection = false; + params.options = QueryPlannerParams::NO_TABLE_SCAN | QueryPlannerParams::INDEX_INTERSECTION; + + addIndex(BSON("a" << 1)); + addIndex(BSON("b" << 1)); + addIndex(BSON("c" << 1)); + + runQuery(fromjson("{a: {$gt: 1}, b: 1, c: 1}")); + + // We should do an AND_SORT intersection of {b: 1} and {c: 1}, but no AND_HASH plans. + assertNumSolutions(4U); + assertSolutionExists("{fetch: {filter: {b: 1, c: 1}, node: {ixscan: " + "{pattern: {a: 1}, bounds: {a: [[1,Infinity,false,true]]}}}}}"); + assertSolutionExists("{fetch: {filter: {a:{$gt:1},c:1}, node: {ixscan: " + "{pattern: {b: 1}, bounds: {b: [[1,1,true,true]]}}}}}"); + assertSolutionExists("{fetch: {filter: {a:{$gt:1},b:1}, node: {ixscan: " + "{pattern: {c: 1}, bounds: {c: [[1,1,true,true]]}}}}}"); + assertSolutionExists("{fetch: {filter: {a:{$gt:1}}, node: {andSorted: {nodes: [" + "{ixscan: {filter: null, pattern: {b:1}}}," + "{ixscan: {filter: null, pattern: {c:1}}}]}}}}"); + + // Restore the old value of the has intersection switch. + internalQueryPlannerEnableHashIntersection = oldEnableHashIntersection; + } + // // Index intersection cases for SERVER-12825: make sure that // we don't generate an ixisect plan if a compound index is |