Search in sources :

Example 11 with Optimizable

use of org.apache.derby.iapi.sql.compile.Optimizable in project derby by apache.

the class XMLOptTrace method traceConsideringConglomerate.

public void traceConsideringConglomerate(ConglomerateDescriptor cd, int tableNumber) {
    Optimizable opt = getOptimizable(tableNumber);
    _currentQueryBlock.currentDecoration = createElement(_currentQueryBlock.currentJoinsElement, DECORATION, null);
    _currentQueryBlock.currentDecoration.setAttribute(DECORATION_CONGLOM_NAME, cd.getConglomerateName());
    _currentQueryBlock.currentDecoration.setAttribute(DECORATION_TABLE_NAME, getOptimizableName(opt).toString());
    _currentQueryBlock.currentDecoration.setAttribute(DECORATION_JOIN_STRATEGY, _currentQueryBlock.currentDecorationStrategy.getName());
    String[] columnNames = cd.getColumnNames();
    if (cd.isIndex() && (columnNames != null)) {
        int[] keyColumns = cd.getIndexDescriptor().baseColumnPositions();
        for (int i = 0; i < keyColumns.length; i++) {
            createElement(_currentQueryBlock.currentDecoration, DECORATION_KEY, columnNames[keyColumns[i] - 1]);
        }
    }
}
Also used : Optimizable(org.apache.derby.iapi.sql.compile.Optimizable)

Example 12 with Optimizable

use of org.apache.derby.iapi.sql.compile.Optimizable in project derby by apache.

the class XMLOptTrace method traceStartQueryBlock.

public void traceStartQueryBlock(long timeOptimizationStarted, int optimizerID, OptimizableList optimizableList) {
    _maxQueryID++;
    if (_currentQueryBlock != null) {
        _queryBlockStack.push(_currentQueryBlock);
    }
    Element queryElement = createElement(_currentStatement, QBLOCK, null);
    queryElement.setAttribute(QBLOCK_OPTIMIZER_ID, Integer.toString(optimizerID));
    queryElement.setAttribute(QBLOCK_START_TIME, formatTimestamp(timeOptimizationStarted));
    queryElement.setAttribute(QBLOCK_ID, Integer.toString(_maxQueryID));
    _currentQueryBlock = new QueryBlock(_maxQueryID, optimizableList, queryElement);
    if (optimizableList != null) {
        for (int i = 0; i < optimizableList.size(); i++) {
            Optimizable opt = optimizableList.getOptimizable(i);
            if (_cm == null) {
                _cm = ((QueryTreeNode) opt).getContextManager();
                _lcc = (LanguageConnectionContext) _cm.getContext(LanguageConnectionContext.CONTEXT_ID);
            }
            Element optElement = createElement(queryElement, QBLOCK_OPTIMIZABLE, getOptimizableName(opt).getFullSQLName());
            optElement.setAttribute(QBLOCK_OPT_TABLE_NUMBER, Integer.toString(opt.getTableNumber()));
        }
    }
}
Also used : Element(org.w3c.dom.Element) Optimizable(org.apache.derby.iapi.sql.compile.Optimizable)

Example 13 with Optimizable

use of org.apache.derby.iapi.sql.compile.Optimizable in project derby by apache.

the class ProjectRestrictNode method optimizeIt.

/**
 * @see Optimizable#optimizeIt
 *
 * @exception StandardException		Thrown on error
 */
@Override
public CostEstimate optimizeIt(Optimizer optimizer, OptimizablePredicateList predList, CostEstimate outerCost, RowOrdering rowOrdering) throws StandardException {
    /*
		** RESOLVE: Most types of Optimizables only implement estimateCost(),
		** and leave it up to optimizeIt() in FromTable to figure out the
		** total cost of the join.  A ProjectRestrict can have a non-Optimizable
		** child, though, in which case we want to tell the child the
		** number of outer rows - it could affect the join strategy
		** significantly.  So we implement optimizeIt() here, which overrides
		** the optimizeIt() in FromTable.  This assumes that the join strategy
		** for which this join node is the inner table is a nested loop join,
		** which will not be a valid assumption when we implement other
		** strategies like materialization (hash join can work only on
		** base tables).  The join strategy for a base table under a
		** ProjectRestrict is set in the base table itself.
		*/
    CostEstimate childCost;
    setCostEstimate(getCostEstimate(optimizer));
    /*
		** Don't re-optimize a child result set that has already been fully
		** optimized.  For example, if the child result set is a SelectNode,
		** it will be changed to a ProjectRestrictNode, which we don't want
		** to re-optimized.
		*/
    // NOTE: TO GET THE RIGHT COST, THE CHILD RESULT MAY HAVE TO BE
    // OPTIMIZED MORE THAN ONCE, BECAUSE THE NUMBER OF OUTER ROWS
    // MAY BE DIFFERENT EACH TIME.
    // if (childResultOptimized)
    // return costEstimate;
    // It's possible that a call to optimize the left/right will cause
    // a new "truly the best" plan to be stored in the underlying base
    // tables.  If that happens and then we decide to skip that plan
    // (which we might do if the call to "considerCost()" below decides
    // the current path is infeasible or not the best) we need to be
    // able to revert back to the "truly the best" plans that we had
    // saved before we got here.  So with this next call we save the
    // current plans using "this" node as the key.  If needed, we'll
    // then make the call to revert the plans in OptimizerImpl's
    // getNextDecoratedPermutation() method.
    updateBestPlanMap(ADD_PLAN, this);
    /* If the childResult is instanceof Optimizable, then we optimizeIt.
		 * Otherwise, we are going into a new query block.  If the new query
		 * block has already had its access path modified, then there is
		 * nothing to do.  Otherwise, we must begin the optimization process
		 * anew on the new query block.
		 */
    if (childResult instanceof Optimizable) {
        childCost = ((Optimizable) childResult).optimizeIt(optimizer, restrictionList, outerCost, rowOrdering);
        /* Copy child cost to this node's cost */
        getCostEstimate().setCost(childCost.getEstimatedCost(), childCost.rowCount(), childCost.singleScanRowCount());
    // Note: we don't call "optimizer.considerCost()" here because
    // a) the child will make that call as part of its own
    // "optimizeIt()" work above, and b) the child might have
    // different criteria for "considering" (i.e. rejecting or
    // accepting) a plan's cost than this ProjectRestrictNode does--
    // and we don't want to override the child's decision.  So as
    // with most operations in this class, if the child is an
    // Optimizable, we just let it do its own work and make its
    // own decisions.
    } else if (!accessPathModified) {
        if (SanityManager.DEBUG) {
            if (!((childResult instanceof SelectNode) || (childResult instanceof RowResultSetNode))) {
                SanityManager.THROWASSERT("childResult is expected to be instanceof " + "SelectNode or RowResultSetNode - it is a " + childResult.getClass().getName());
            }
        }
        childResult = childResult.optimize(optimizer.getDataDictionary(), restrictionList, outerCost.rowCount());
        /* Copy child cost to this node's cost */
        childCost = childResult.getCostEstimate();
        getCostEstimate().setCost(childCost.getEstimatedCost(), childCost.rowCount(), childCost.singleScanRowCount());
        /* Note: Prior to the fix for DERBY-781 we had calls here
			 * to set the cost estimate for BestAccessPath and
			 * BestSortAvoidancePath to equal costEstimate.  That used
			 * to be okay because prior to DERBY-781 we would only
			 * get here once (per join order) for a given SelectNode/
			 * RowResultSetNode and thus we could safely say that the
			 * costEstimate from the most recent call to "optimize()"
			 * was the best one so far (because we knew that we would
			 * only call childResult.optimize() once).  Now that we
			 * support hash joins with subqueries, though, we can get
			 * here twice per join order: once when the optimizer is
			 * considering a nested loop join with this PRN, and once
			 * when it is considering a hash join.  This means we can't
			 * just arbitrarily use the cost estimate for the most recent
			 * "optimize()" as the best cost because that may not
			 * be accurate--it's possible that the above call to
			 * childResult.optimize() was for a hash join, but that
			 * we were here once before (namely for nested loop) and
			 * the cost of the nested loop is actually less than
			 * the cost of the hash join.  In that case it would
			 * be wrong to use costEstimate as the cost of the "best"
			 * paths because it (costEstimate) holds the cost of
			 * the hash join, not of the nested loop join.  So with
			 * DERBY-781 the following calls were removed:
			 *   getBestAccessPath().setCostEstimate(costEstimate);
			 *   getBestSortAvoidancePath().setCostEstimate(costEstimate);
			 * If costEstimate *does* actually hold the estimate for
			 * the best path so far, then we will set BestAccessPath
			 * and BestSortAvoidancePath as needed in the following
			 * call to "considerCost".
			 */
        // childResultOptimized = true;
        /* RESOLVE - ARBITRARYHASHJOIN - Passing restriction list here, as above, is correct.
			 * However,  passing predList makes the following work:
			 *	select * from t1, (select * from t2) c properties joinStrategy = hash where t1.c1 = c.c1;
			 * The following works with restrictionList:
			 *	select * from t1, (select c1 + 0 from t2) c(c1) properties joinStrategy = hash where t1.c1 = c.c1;
			 */
        optimizer.considerCost(this, restrictionList, getCostEstimate(), outerCost);
    }
    return getCostEstimate();
}
Also used : CostEstimate(org.apache.derby.iapi.sql.compile.CostEstimate) Optimizable(org.apache.derby.iapi.sql.compile.Optimizable)

Example 14 with Optimizable

use of org.apache.derby.iapi.sql.compile.Optimizable in project derby by apache.

the class UnionNode method modifyAccessPath.

/**
 * @see Optimizable#modifyAccessPath
 *
 * @exception StandardException		Thrown on error
 */
@Override
public Optimizable modifyAccessPath(JBitSet outerTables) throws StandardException {
    Optimizable retOptimizable;
    retOptimizable = super.modifyAccessPath(outerTables);
    /* We only want call addNewNodes() once */
    if (addNewNodesCalled) {
        return retOptimizable;
    }
    return (Optimizable) addNewNodes();
}
Also used : Optimizable(org.apache.derby.iapi.sql.compile.Optimizable)

Example 15 with Optimizable

use of org.apache.derby.iapi.sql.compile.Optimizable in project derby by apache.

the class SetOperatorNode method modifyAccessPath.

/**
 * @see Optimizable#modifyAccessPath
 *
 * @exception StandardException		Thrown on error
 */
public Optimizable modifyAccessPath(JBitSet outerTables, PredicateList predList) throws StandardException {
    // is the equijoin predicate that is required by hash join.
    if ((predList != null) && !getTrulyTheBestAccessPath().getJoinStrategy().isHashJoin()) {
        for (int i = predList.size() - 1; i >= 0; i--) if (pushOptPredicate(predList.getOptPredicate(i)))
            predList.removeOptPredicate(i);
    }
    /*
		 * It's possible that we tried to push a predicate down to this node's
		 * children but failed to do so.  This can happen if this node's
		 * children both match the criteria for pushing a predicate (namely,
		 * they reference base tables) but the children's children do not.
		 * Ex.
		 *  select * from
		 *    (select i,j from t2 UNION
		 *      values (1,1),(2,2),(3,3),(4,4) UNION
		 *      select i,j from t1
		 *    ) x0 (i,j),
		 *    t5 where x0.i = t5.i;
		 *
		 * This will yield a tree resembling the following:
		 *
		 *                     UNION
		 *                    /     \
		 *               UNION     SELECT (T1)
		 *              /     \
		 *        SELECT (T2)  VALUES
		 *
		 * In this case the top UNION ("this") will push the predicate down,
		 * but the second UNION will _not_ push the predicate because
		 * it can't be pushed to the VALUES clause.  This means that
		 * after we're done modifying the paths for "this" node (the top
		 * UNION), the predicate will still be sitting in our leftOptPredicates
		 * list.  If that's the case, then we have to make sure the predicate,
		 * which was _not_ enforced in the left child, is enforced at this
		 * level.  We do that by generating a ProjectRestrictNode above this
		 * node.  Yes, this means the predicate will actually be applied
		 * twice to the right child (in this case), but that's okay as it
		 * won't affect the results.
		 */
    // Get the cost estimate for this node so that we can put it in
    // the new ProjectRestrictNode, if one is needed.
    CostEstimate ce = getFinalCostEstimate();
    // Modify this node's access paths.
    ResultSetNode topNode = (ResultSetNode) modifyAccessPath(outerTables);
    /* Now see if there are any left over predicates; if so, then we
		 * have to generate a ProjectRestrictNode.  Note: we want to check
		 * all SetOpNodes that exist in the subtree rooted at this SetOpNode.
		 * Since we just modified access paths on this node, it's possible
		 * that the SetOperatorNode chain (if there was one) is now "broken"
		 * as a result of the insertion of new nodes.  For example, prior
		 * to modification of access paths we may have a chain such as:
		 *
		 *                          UnionNode (0)
		 *                          /       \
		 *                 UnionNode (1)    SelectNode (2)
		 *                 /        \ 
		 *      SelectNode (3)     SelectNode (4)
		 *
		 * Now if UnionNode(1) did not specify "ALL" then as part of the
		 * above call to modifyAccessPaths() we will have inserted a
		 * DistinctNode above it, thus giving:
		 *
		 *                          UnionNode (0)
		 *                          /       \
		 *                 DistinctNode (5)  SelectNode (2)
		 *                      |
		 *                 UnionNode (1)
		 *                 /        \ 
		 *      SelectNode (3)     SelectNode (4)
		 *
		 * So our chain of UnionNode's has now been "broken" by an intervening
		 * DistinctNode.  For this reason we can't just walk the chain of
		 * SetOperatorNodes looking for unpushed predicates (because the
		 * chain might be broken and then we could miss some nodes). Instead,
		 * we have to get a collection of all relevant nodes that exist beneath
		 * this SetOpNode and call hasUnPushedPredicates() on each one.  For
		 * now we only consider UnionNodes to be "relevant" because those are
		 * the only ones that might actually have unpushed predicates.
		 * 
		 * If we find any UnionNodes that *do* have unpushed predicates then
		 * we have to use a PRN to enforce the predicate at the level of
		 * this, the top-most, SetOperatorNode.
		 */
    // Find all UnionNodes in the subtree.
    CollectNodesVisitor<UnionNode> cnv = new CollectNodesVisitor<UnionNode>(UnionNode.class);
    this.accept(cnv);
    // Now see if any of them have unpushed predicates.
    boolean genPRN = false;
    for (UnionNode node : cnv.getList()) {
        if (node.hasUnPushedPredicates()) {
            genPRN = true;
            break;
        }
    }
    if (genPRN) {
        // When we generate the project restrict node, we pass in the
        // "pushedPredicates" list because that has the predicates in
        // _unscoped_ form, which means they are intended for _this_
        // node instead of this node's children.  That's exactly what
        // we want.
        ResultSetNode prnRSN = new ProjectRestrictNode(// Child ResultSet
        topNode, // Projection
        topNode.getResultColumns(), // Restriction
        null, // Restriction as PredicateList
        pushedPredicates, // Subquerys in Projection
        null, // Subquerys in Restriction
        null, // Table properties
        null, getContextManager());
        prnRSN.setCostEstimate(ce.cloneMe());
        prnRSN.setReferencedTableMap(topNode.getReferencedTableMap());
        topNode = prnRSN;
    }
    return (Optimizable) topNode;
}
Also used : CostEstimate(org.apache.derby.iapi.sql.compile.CostEstimate) Optimizable(org.apache.derby.iapi.sql.compile.Optimizable)

Aggregations

Optimizable (org.apache.derby.iapi.sql.compile.Optimizable)23 CostEstimate (org.apache.derby.iapi.sql.compile.CostEstimate)9 AccessPath (org.apache.derby.iapi.sql.compile.AccessPath)3 OptimizerPlan (org.apache.derby.iapi.sql.compile.OptimizerPlan)2 JBitSet (org.apache.derby.iapi.util.JBitSet)2 Element (org.w3c.dom.Element)2 ParserConfigurationException (javax.xml.parsers.ParserConfigurationException)1 JoinStrategy (org.apache.derby.iapi.sql.compile.JoinStrategy)1 OptimizablePredicate (org.apache.derby.iapi.sql.compile.OptimizablePredicate)1 OptimizablePredicateList (org.apache.derby.iapi.sql.compile.OptimizablePredicateList)1 ConglomerateDescriptor (org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)1 UniqueTupleDescriptor (org.apache.derby.iapi.sql.dictionary.UniqueTupleDescriptor)1 StandardException (org.apache.derby.shared.common.error.StandardException)1