summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2014-09-09 15:33:23 -0400
committerDavid Storch <david.storch@10gen.com>2014-09-17 09:37:26 -0400
commit775777b99c575edff05262140fbd529316aee939 (patch)
tree27159ce6583fca179afb48bd1fd05c1ed5c3173d
parentddce701ed775996f2a49fc949e26c5bcbc38fe84 (diff)
downloadmongo-775777b99c575edff05262140fbd529316aee939.tar.gz
SERVER-15279 disable hash-based index intersection by default
(cherry picked from commit 5e2b3c29b438f936eeb0a675e70e0131ab4c145a) Conflicts: src/mongo/dbtests/plan_ranking.cpp
-rw-r--r--src/mongo/db/query/planner_access.cpp14
-rw-r--r--src/mongo/db/query/query_knobs.cpp2
-rw-r--r--src/mongo/db/query/query_knobs.h3
-rw-r--r--src/mongo/db/query/query_planner_test.cpp31
-rw-r--r--src/mongo/dbtests/plan_ranking.cpp17
5 files changed, 64 insertions, 3 deletions
diff --git a/src/mongo/db/query/planner_access.cpp b/src/mongo/db/query/planner_access.cpp
index 89d9284c979..ef946214fe0 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"
@@ -851,7 +852,7 @@ namespace mongo {
asn->children.swap(ixscanNodes);
andResult = asn;
}
- else {
+ else if (internalQueryPlannerEnableHashIntersection) {
AndHashNode* ahn = new AndHashNode();
ahn->children.swap(ixscanNodes);
andResult = ahn;
@@ -867,6 +868,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 877a76c33b4..b7ab829a738 100644
--- a/src/mongo/db/query/query_planner_test.cpp
+++ b/src/mongo/db/query/query_planner_test.cpp
@@ -52,6 +52,7 @@ namespace {
class QueryPlannerTest : public mongo::unittest::Test {
protected:
void setUp() {
+ internalQueryPlannerEnableHashIntersection = true;
params.options = QueryPlannerParams::INCLUDE_COLLSCAN;
addIndex(BSON("_id" << 1));
}
@@ -4075,6 +4076,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
diff --git a/src/mongo/dbtests/plan_ranking.cpp b/src/mongo/dbtests/plan_ranking.cpp
index 02efa06321b..6124d4417b6 100644
--- a/src/mongo/dbtests/plan_ranking.cpp
+++ b/src/mongo/dbtests/plan_ranking.cpp
@@ -51,6 +51,8 @@ namespace mongo {
// How we access the external setParameter testing bool.
extern bool internalQueryForceIntersectionPlans;
+ extern bool internalQueryPlannerEnableHashIntersection;
+
} // namespace mongo
namespace PlanRankingTests {
@@ -62,14 +64,21 @@ namespace PlanRankingTests {
class PlanRankingTestBase {
public:
- PlanRankingTestBase() : _internalQueryForceIntersectionPlans(internalQueryForceIntersectionPlans) {
+ PlanRankingTestBase()
+ : _internalQueryForceIntersectionPlans(internalQueryForceIntersectionPlans),
+ _enableHashIntersection(internalQueryPlannerEnableHashIntersection) {
+
+ // Run all tests with hash-based intersection enabled.
+ internalQueryPlannerEnableHashIntersection = true;
+
Client::WriteContext ctx(ns);
_client.dropCollection(ns);
}
virtual ~PlanRankingTestBase() {
- // Restore external setParameter testing bool.
+ // Restore external setParameter testing bools.
internalQueryForceIntersectionPlans = _internalQueryForceIntersectionPlans;
+ internalQueryPlannerEnableHashIntersection = _enableHashIntersection;
}
void insert(const BSONObj& obj) {
@@ -160,6 +169,10 @@ namespace PlanRankingTests {
// Holds the value of global "internalQueryForceIntersectionPlans" setParameter flag.
// Restored at end of test invocation regardless of test result.
bool _internalQueryForceIntersectionPlans;
+
+ // Holds the value of the global set parameter so it can be restored at the end
+ // of the test.
+ bool _enableHashIntersection;
};
DBDirectClient PlanRankingTestBase::_client;