* c) the data table plan
* @param plans the list of candidate plans
* @return QueryPlan
*/
private QueryPlan chooseBestPlan(SelectStatement select, List<QueryPlan> plans) {
final QueryPlan dataPlan = plans.get(0);
if (plans.size() == 1) {
return dataPlan;
}
/**
* If we have a plan(s) that are just point lookups (i.e. fully qualified row
* keys), then favor those first.
*/
List<QueryPlan> candidates = Lists.newArrayListWithExpectedSize(plans.size());
for (QueryPlan plan : plans) {
if (plan.getContext().getScanRanges().isPointLookup()) {
candidates.add(plan);
}
}
/**
* If we have a plan(s) that removes the order by, choose from among these,
* as this is typically the most expensive operation. Once we have stats, if
* there's a limit on the query, we might choose a different plan. For example
* if the limit was a very large number and the combination of applying other
* filters on the row key are estimated to choose fewer rows, we'd choose that
* one.
*/
List<QueryPlan> stillCandidates = plans;
List<QueryPlan> bestCandidates = candidates;
if (!candidates.isEmpty()) {
stillCandidates = candidates;
bestCandidates = Lists.<QueryPlan>newArrayListWithExpectedSize(candidates.size());
}
for (QueryPlan plan : stillCandidates) {
// If ORDER BY optimized out (or not present at all)
if (plan.getOrderBy().getOrderByExpressions().isEmpty()) {
bestCandidates.add(plan);
}
}
if (bestCandidates.isEmpty()) {
bestCandidates.addAll(stillCandidates);
}
int nViewConstants = 0;
PTable dataTable = dataPlan.getTableRef().getTable();
if (dataTable.getType() == PTableType.VIEW) {
for (PColumn column : dataTable.getColumns()) {
if (column.getViewConstant() != null) {
nViewConstants++;
}