summaryrefslogtreecommitdiff
path: root/src/mongo/db/query
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2014-09-17 09:38:54 -0400
committerDavid Storch <david.storch@10gen.com>2014-09-17 09:38:54 -0400
commit8baf068f5c7bcb52c7cc19bd6343fc2569cd92fc (patch)
tree88c193cad7e3fd741f1ace817958055251aa8dde /src/mongo/db/query
parent47260bcc495c093e5a2542a3d2ccdd43e796a369 (diff)
downloadmongo-8baf068f5c7bcb52c7cc19bd6343fc2569cd92fc.tar.gz
SERVER-15279 disable hash-based index intersection by default
Diffstat (limited to 'src/mongo/db/query')
-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
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