mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
SERVER-15217 remove unused tests in dbtests/plan_ranking.cpp
Closes #985 Signed-off-by: Jason Rassi <rassi@10gen.com>
This commit is contained in:
parent
dd560fcda0
commit
f9043a51b1
@ -505,217 +505,6 @@ namespace PlanRankingTests {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Index intersection solutions can be covered when single-index solutions
|
||||
* are not. If the single-index solutions need to do a lot of fetching,
|
||||
* then ixisect should win.
|
||||
*/
|
||||
class PlanRankingIxisectCovered : public PlanRankingTestBase {
|
||||
public:
|
||||
void run() {
|
||||
// Neither 'a' nor 'b' is selective.
|
||||
for (int i = 0; i < N; ++i) {
|
||||
insert(BSON("a" << 1 << "b" << 1));
|
||||
}
|
||||
|
||||
// Add indices on 'a' and 'b'.
|
||||
addIndex(BSON("a" << 1));
|
||||
addIndex(BSON("b" << 1));
|
||||
|
||||
// Query {a:1, b:1}, and project out all fields other than 'a' and 'b'.
|
||||
CanonicalQuery* cq;
|
||||
ASSERT(CanonicalQuery::canonicalize(ns,
|
||||
BSON("a" << 1 << "b" << 1),
|
||||
BSONObj(),
|
||||
BSON("_id" << 0 << "a" << 1 << "b" << 1),
|
||||
&cq).isOK());
|
||||
ASSERT(NULL != cq);
|
||||
std::unique_ptr<CanonicalQuery> killCq(cq);
|
||||
|
||||
// We should choose an ixisect plan because it requires fewer fetches.
|
||||
// Takes ownership of cq.
|
||||
QuerySolution* soln = pickBestPlan(cq);
|
||||
ASSERT(QueryPlannerTestLib::solutionMatches(
|
||||
"{proj: {spec: {_id:0,a:1,b:1}, node: {andSorted: {nodes: ["
|
||||
"{ixscan: {filter: null, pattern: {a:1}}},"
|
||||
"{ixscan: {filter: null, pattern: {b:1}}}]}}}}",
|
||||
soln->root.get()));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Use the same data, same indices, and same query as the previous
|
||||
* test case, except without the projection. The query is not covered
|
||||
* by the index in this case, which means that there is no advantage
|
||||
* to an index intersection solution.
|
||||
*/
|
||||
class PlanRankingIxisectNonCovered : public PlanRankingTestBase {
|
||||
public:
|
||||
void run() {
|
||||
// Neither 'a' nor 'b' is selective.
|
||||
for (int i = 0; i < N; ++i) {
|
||||
insert(BSON("a" << 1 << "b" << 1));
|
||||
}
|
||||
|
||||
// Add indices on 'a' and 'b'.
|
||||
addIndex(BSON("a" << 1));
|
||||
addIndex(BSON("b" << 1));
|
||||
|
||||
// Query {a:1, b:1}.
|
||||
CanonicalQuery* cq;
|
||||
ASSERT(CanonicalQuery::canonicalize(ns,
|
||||
BSON("a" << 1 << "b" << 1),
|
||||
&cq).isOK());
|
||||
ASSERT(NULL != cq);
|
||||
std::unique_ptr<CanonicalQuery> killCq(cq);
|
||||
|
||||
// The intersection is large, and ixisect does not make the
|
||||
// query covered. We should NOT choose an intersection plan.
|
||||
QuerySolution* soln = pickBestPlan(cq);
|
||||
bool bestIsScanOverA = QueryPlannerTestLib::solutionMatches(
|
||||
"{fetch: {node: {ixscan: {pattern: {a: 1}}}}}",
|
||||
soln->root.get());
|
||||
bool bestIsScanOverB = QueryPlannerTestLib::solutionMatches(
|
||||
"{fetch: {node: {ixscan: {pattern: {b: 1}}}}}",
|
||||
soln->root.get());
|
||||
ASSERT(bestIsScanOverA || bestIsScanOverB);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Index intersection solutions may require fewer fetches even if it does not make the
|
||||
* query covered. The ixisect plan will scan as many index keys as the union of the two
|
||||
* single index plans, but only needs to retrieve full documents for the intersection
|
||||
* of the two plans---this could mean fewer fetches!
|
||||
*/
|
||||
class PlanRankingNonCoveredIxisectFetchesLess : public PlanRankingTestBase {
|
||||
public:
|
||||
void run() {
|
||||
// Set up data so that the following conditions hold:
|
||||
// 1) Documents matching {a: 1} are of high cardinality.
|
||||
// 2) Documents matching {b: 1} are of high cardinality.
|
||||
// 3) Documents matching {a: 1, b: 1} are of low cardinality---
|
||||
// the intersection is small.
|
||||
// 4) At least one of the documents in the intersection is
|
||||
// returned during the trial period.
|
||||
insert(BSON("a" << 1 << "b" << 1));
|
||||
for (int i = 0; i < N/2; ++i) {
|
||||
insert(BSON("a" << 1 << "b" << 2));
|
||||
}
|
||||
for (int i = 0; i < N/2; ++i) {
|
||||
insert(BSON("a" << 2 << "b" << 1));
|
||||
}
|
||||
|
||||
// Add indices on 'a' and 'b'.
|
||||
addIndex(BSON("a" << 1));
|
||||
addIndex(BSON("b" << 1));
|
||||
|
||||
// Neither the predicate on 'b' nor the predicate on 'a' is
|
||||
// very selective: both retrieve about half the documents.
|
||||
// However, the intersection is very small, which makes
|
||||
// the intersection plan desirable.
|
||||
CanonicalQuery* cq;
|
||||
ASSERT(CanonicalQuery::canonicalize(ns,
|
||||
fromjson("{a: 1, b: 1}"),
|
||||
&cq).isOK());
|
||||
ASSERT(NULL != cq);
|
||||
std::unique_ptr<CanonicalQuery> killCq(cq);
|
||||
|
||||
QuerySolution* soln = pickBestPlan(cq);
|
||||
ASSERT(QueryPlannerTestLib::solutionMatches(
|
||||
"{fetch: {node: {andSorted: {nodes: ["
|
||||
"{ixscan: {filter: null, pattern: {a:1}}},"
|
||||
"{ixscan: {filter: null, pattern: {b:1}}}]}}}}",
|
||||
soln->root.get()));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* If the intersection is small, an AND_SORTED plan may be able to
|
||||
* hit EOF before the single index plans.
|
||||
*/
|
||||
class PlanRankingIxisectHitsEOFFirst : public PlanRankingTestBase {
|
||||
public:
|
||||
void run() {
|
||||
// Set up the data so that for the query {a: 1, b: 1}, the
|
||||
// intersection is empty. The single index plans have to do
|
||||
// more fetching from disk in order to determine that the result
|
||||
// set is empty. As a result, the intersection plan hits EOF first.
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
insert(BSON("a" << 1 << "b" << 2));
|
||||
}
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
insert(BSON("a" << 2 << "b" << 1));
|
||||
}
|
||||
for (int i = 0; i < N; ++i) {
|
||||
insert(BSON("a" << 2 << "b" << 2));
|
||||
}
|
||||
|
||||
// Add indices on 'a' and 'b'.
|
||||
addIndex(BSON("a" << 1));
|
||||
addIndex(BSON("b" << 1));
|
||||
|
||||
CanonicalQuery* cq;
|
||||
ASSERT(CanonicalQuery::canonicalize(ns,
|
||||
fromjson("{a: 1, b: 1}"),
|
||||
&cq).isOK());
|
||||
ASSERT(NULL != cq);
|
||||
std::unique_ptr<CanonicalQuery> killCq(cq);
|
||||
|
||||
// Choose the index intersection plan.
|
||||
QuerySolution* soln = pickBestPlan(cq);
|
||||
ASSERT(QueryPlannerTestLib::solutionMatches(
|
||||
"{fetch: {node: {andSorted: {nodes: ["
|
||||
"{ixscan: {filter: null, pattern: {a:1}}},"
|
||||
"{ixscan: {filter: null, pattern: {b:1}}}]}}}}",
|
||||
soln->root.get()));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* If we query on 'a', 'b', and 'c' with indices on all three fields,
|
||||
* then there are three possible size-2 index intersections to consider.
|
||||
* Make sure we choose the right one.
|
||||
*/
|
||||
class PlanRankingChooseBetweenIxisectPlans : public PlanRankingTestBase {
|
||||
public:
|
||||
void run() {
|
||||
// Set up the data so that for the query {a: 1, b: 1, c: 1}, the intersection
|
||||
// between 'b' and 'c' is small, and the other intersections are larger.
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
insert(BSON("a" << 1 << "b" << 1 << "c" << 1));
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
insert(BSON("a" << 2 << "b" << 1 << "c" << 1));
|
||||
}
|
||||
for (int i = 0; i < N/2; ++i) {
|
||||
insert(BSON("a" << 1 << "b" << 1 << "c" << 2));
|
||||
insert(BSON("a" << 1 << "b" << 2 << "c" << 1));
|
||||
}
|
||||
|
||||
// Add indices on 'a', 'b', and 'c'.
|
||||
addIndex(BSON("a" << 1));
|
||||
addIndex(BSON("b" << 1));
|
||||
addIndex(BSON("c" << 1));
|
||||
|
||||
CanonicalQuery* cq;
|
||||
ASSERT(CanonicalQuery::canonicalize(ns,
|
||||
fromjson("{a: 1, b: 1, c: 1}"),
|
||||
&cq).isOK());
|
||||
ASSERT(NULL != cq);
|
||||
std::unique_ptr<CanonicalQuery> killCq(cq);
|
||||
|
||||
// Intersection between 'b' and 'c' should hit EOF while the
|
||||
// other plans are busy fetching documents.
|
||||
QuerySolution* soln = pickBestPlan(cq);
|
||||
ASSERT(QueryPlannerTestLib::solutionMatches(
|
||||
"{fetch: {node: {andSorted: {nodes: ["
|
||||
"{ixscan: {filter: null, pattern: {b:1}}},"
|
||||
"{ixscan: {filter: null, pattern: {c:1}}}]}}}}",
|
||||
soln->root.get()));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* When no other information is available, prefer solutions without
|
||||
* a blocking sort stage.
|
||||
@ -835,12 +624,6 @@ namespace PlanRankingTests {
|
||||
add<PlanRankingPreferImmediateEOFAgainstHashed>();
|
||||
add<PlanRankingNoCollscan>();
|
||||
add<PlanRankingCollscan>();
|
||||
// TODO: These don't work without counting FETCH and FETCH is now gone.
|
||||
// add<PlanRankingIxisectCovered>();
|
||||
// add<PlanRankingIxisectNonCovered>();
|
||||
// add<PlanRankingNonCoveredIxisectFetchesLess>();
|
||||
// add<PlanRankingIxisectHitsEOFFirst>();
|
||||
// add<PlanRankingChooseBetweenIxisectPlans>();
|
||||
add<PlanRankingAvoidBlockingSort>();
|
||||
add<PlanRankingWorkPlansLongEnough>();
|
||||
add<PlanRankingAccountForKeySkips>();
|
||||
|
Loading…
Reference in New Issue
Block a user