use of org.apache.derby.iapi.sql.compile.AccessPath in project derby by apache.
the class OptimizerImpl method considerCost.
/**
* This is the version of costOptimizable for non-base-tables.
*
* @see Optimizer#considerCost
*
* @exception StandardException Thrown on error
*/
public void considerCost(Optimizable optimizable, OptimizablePredicateList predList, CostEstimate estimatedCost, CostEstimate outerCost) throws StandardException {
/*
** Don't consider non-feasible join strategies.
*/
if (!optimizable.feasibleJoinStrategy(predList, this)) {
return;
}
// Before considering the cost, make sure we set the optimizable's
// "current" cost to be the one that we received. Doing this allows
// us to compare "current" with "best" later on to find out if
// the "current" plan is also the "best" one this round--if it's
// not then we'll have to revert back to whatever the best plan is.
// That check is performed in getNextDecoratedPermutation() of
// this class.
optimizable.getCurrentAccessPath().setCostEstimate(estimatedCost);
// DERBY-1259.
if (!optimizable.memoryUsageOK(estimatedCost.rowCount() / outerCost.rowCount(), maxMemoryPerTable)) {
if (tracingIsOn()) {
tracer().traceSkippingBecauseTooMuchMemory(maxMemoryPerTable);
}
return;
}
/* Pick the cheapest cost for this particular optimizable.
* NOTE: Originally, the code only chose the new access path if
* it was cheaper than the old access path. However, I (Jerry)
* found that the new and old costs were the same for a derived
* table and the old access path did not have a join strategy
* associated with it in that case. So, we now choose the new
* access path if it is the same cost or cheaper than the current
* access path.
*/
AccessPath ap = optimizable.getBestAccessPath();
CostEstimate bestCostEstimate = ap.getCostEstimate();
if ((bestCostEstimate == null) || bestCostEstimate.isUninitialized() || (estimatedCost.compare(bestCostEstimate) <= 0)) {
ap.setCostEstimate(estimatedCost);
optimizable.rememberJoinStrategyAsBest(ap);
}
/*
** Keep track of the best sort-avoidance path if there is a
** required row ordering.
*/
if (requiredRowOrdering != null) {
/*
** The current optimizable can avoid a sort only if the
** outer one does, also (if there is an outer one).
*/
if (joinPosition == 0 || optimizableList.getOptimizable(proposedJoinOrder[joinPosition - 1]).considerSortAvoidancePath()) {
/*
** There is a required row ordering - does the proposed access
** path avoid a sort?
*/
if (requiredRowOrdering.sortRequired(currentRowOrdering, assignedTableMap, optimizableList, proposedJoinOrder) == RequiredRowOrdering.NOTHING_REQUIRED) {
ap = optimizable.getBestSortAvoidancePath();
bestCostEstimate = ap.getCostEstimate();
/* Is this the cheapest sort-avoidance path? */
if ((bestCostEstimate == null) || bestCostEstimate.isUninitialized() || (estimatedCost.compare(bestCostEstimate) < 0)) {
ap.setCostEstimate(estimatedCost);
optimizable.rememberJoinStrategyAsBest(ap);
optimizable.rememberSortAvoidancePath();
/*
** Remember the current row ordering as best
*/
currentRowOrdering.copy(bestRowOrdering);
}
}
}
}
}
use of org.apache.derby.iapi.sql.compile.AccessPath in project derby by apache.
the class OptimizerImpl method ruleBasedCostOptimizable.
/**
* This method decides whether the given conglomerate descriptor is
* cheapest based on rules, rather than based on cost estimates.
* The rules are:
*
* Covering matching indexes are preferred above all
* Non-covering matching indexes are next in order of preference
* Covering non-matching indexes are next in order of preference
* Heap scans are next in order of preference
* Non-covering, non-matching indexes are last in order of
* preference.
*
* In the current language architecture, there will always be a
* heap, so a non-covering, non-matching index scan will never be
* chosen. However, the optimizer may see a non-covering, non-matching
* index first, in which case it will choose it temporarily as the
* best conglomerate seen so far.
*
* NOTE: This method sets the cost in the optimizable, even though it
* doesn't use the cost to determine which access path to choose. There
* are two reasons for this: the cost might be needed to determine join
* order, and the cost information is copied to the query plan.
*/
private void ruleBasedCostOptimizable(Optimizable optimizable, TableDescriptor td, ConglomerateDescriptor cd, OptimizablePredicateList predList, CostEstimate outerCost) throws StandardException {
/* CHOOSE BEST CONGLOMERATE HERE */
AccessPath bestAp = optimizable.getBestAccessPath();
/*
** If there is more than one conglomerate descriptor
** choose any index that is potentially useful.
*/
if (predList != null && predList.useful(optimizable, cd)) {
/*
** Do not let a non-covering matching index scan supplant a
** covering matching index scan.
*/
boolean newCoveringIndex = optimizable.isCoveringIndex(cd);
if ((!bestAp.getCoveringIndexScan()) || bestAp.getNonMatchingIndexScan() || newCoveringIndex) {
bestAp.setCostEstimate(estimateTotalCost(predList, cd, outerCost, optimizable));
bestAp.setConglomerateDescriptor(cd);
bestAp.setNonMatchingIndexScan(false);
bestAp.setCoveringIndexScan(newCoveringIndex);
bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode());
optimizable.rememberJoinStrategyAsBest(bestAp);
}
return;
}
/* Remember the "last" covering index.
* NOTE - Since we don't have costing, we just go for the
* last one since that's as good as any
*/
if (optimizable.isCoveringIndex(cd)) {
bestAp.setCostEstimate(estimateTotalCost(predList, cd, outerCost, optimizable));
bestAp.setConglomerateDescriptor(cd);
bestAp.setNonMatchingIndexScan(true);
bestAp.setCoveringIndexScan(true);
bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode());
optimizable.rememberJoinStrategyAsBest(bestAp);
return;
}
/*
** If this is the heap, and the best conglomerate so far is a
** non-covering, non-matching index scan, pick the heap.
*/
if ((!bestAp.getCoveringIndexScan()) && bestAp.getNonMatchingIndexScan() && (!cd.isIndex())) {
bestAp.setCostEstimate(estimateTotalCost(predList, cd, outerCost, optimizable));
bestAp.setConglomerateDescriptor(cd);
bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode());
optimizable.rememberJoinStrategyAsBest(bestAp);
/*
** No need to set non-matching index scan and covering
** index scan, as these are already correct.
*/
return;
}
/*
** If all else fails, and no conglomerate has been picked yet,
** pick this one.
*/
ConglomerateDescriptor bestConglomerateDescriptor = bestAp.getConglomerateDescriptor();
if (bestConglomerateDescriptor == null) {
bestAp.setCostEstimate(estimateTotalCost(predList, cd, outerCost, optimizable));
bestAp.setConglomerateDescriptor(cd);
/*
** We have determined above that this index is neither covering
** nor matching.
*/
bestAp.setCoveringIndexScan(false);
bestAp.setNonMatchingIndexScan(cd.isIndex());
bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode());
optimizable.rememberJoinStrategyAsBest(bestAp);
}
}
Aggregations