Search in sources :

Example 16 with AccessPath

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);
                }
            }
        }
    }
}
Also used : AccessPath(org.apache.derby.iapi.sql.compile.AccessPath) CostEstimate(org.apache.derby.iapi.sql.compile.CostEstimate)

Example 17 with AccessPath

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);
    }
}
Also used : AccessPath(org.apache.derby.iapi.sql.compile.AccessPath) ConglomerateDescriptor(org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)

Aggregations

AccessPath (org.apache.derby.iapi.sql.compile.AccessPath)17 CostEstimate (org.apache.derby.iapi.sql.compile.CostEstimate)5 JoinStrategy (org.apache.derby.iapi.sql.compile.JoinStrategy)5 OptimizablePredicateList (org.apache.derby.iapi.sql.compile.OptimizablePredicateList)4 ConglomerateDescriptor (org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)4 Optimizable (org.apache.derby.iapi.sql.compile.Optimizable)3 OptimizablePredicate (org.apache.derby.iapi.sql.compile.OptimizablePredicate)3 FormatableBitSet (org.apache.derby.iapi.services.io.FormatableBitSet)2 Optimizer (org.apache.derby.iapi.sql.compile.Optimizer)2 IndexRowGenerator (org.apache.derby.iapi.sql.dictionary.IndexRowGenerator)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 ParserConfigurationException (javax.xml.parsers.ParserConfigurationException)1 IndexDescriptor (org.apache.derby.catalog.IndexDescriptor)1 OptimizerPlan (org.apache.derby.iapi.sql.compile.OptimizerPlan)1 UniqueTupleDescriptor (org.apache.derby.iapi.sql.dictionary.UniqueTupleDescriptor)1 StoreCostController (org.apache.derby.iapi.store.access.StoreCostController)1 DataValueDescriptor (org.apache.derby.iapi.types.DataValueDescriptor)1 StandardException (org.apache.derby.shared.common.error.StandardException)1