use of org.apache.derby.iapi.sql.compile.AccessPath in project derby by apache.
the class FromTable method updateBestPlanMap.
/**
* @see Optimizable#updateBestPlanMap
*/
public void updateBestPlanMap(short action, Object planKey) throws StandardException {
if (action == REMOVE_PLAN) {
if (bestPlanMap != null) {
bestPlanMap.remove(planKey);
if (bestPlanMap.isEmpty()) {
bestPlanMap = null;
}
}
return;
}
AccessPath bestPath = getTrulyTheBestAccessPath();
AccessPathImpl ap = null;
if (action == ADD_PLAN) {
// there will be no best path--so there's nothing to do.
if (bestPath == null)
return;
// AccessPath for the received key and use that if we can.
if (bestPlanMap == null)
bestPlanMap = new HashMap<Object, AccessPathImpl>();
else
ap = bestPlanMap.get(planKey);
// otherwise just pass null.
if (ap == null) {
if (planKey instanceof Optimizer)
ap = new AccessPathImpl((Optimizer) planKey);
else
ap = new AccessPathImpl((Optimizer) null);
}
ap.copy(bestPath);
bestPlanMap.put(planKey, ap);
return;
}
// join order for which there was no valid plan.
if (bestPlanMap == null)
return;
ap = bestPlanMap.get(planKey);
// the key, in which case there's nothing to load.
if ((ap == null) || (ap.getCostEstimate() == null))
return;
// We found a best plan in our map, so load it into this Optimizable's
// trulyTheBestAccessPath field.
bestPath.copy(ap);
}
use of org.apache.derby.iapi.sql.compile.AccessPath in project derby by apache.
the class FromTable method rememberAsBest.
/**
* @see Optimizable#rememberAsBest
*/
public void rememberAsBest(int planType, Optimizer optimizer) throws StandardException {
AccessPath bestPath = null;
switch(planType) {
case Optimizer.NORMAL_PLAN:
bestPath = getBestAccessPath();
break;
case Optimizer.SORT_AVOIDANCE_PLAN:
bestPath = getBestSortAvoidancePath();
break;
default:
if (SanityManager.DEBUG) {
SanityManager.THROWASSERT("Invalid plan type " + planType);
}
}
getTrulyTheBestAccessPath().copy(bestPath);
// just end up duplicating the work.
if (!(this instanceof ProjectRestrictNode))
updateBestPlanMap(ADD_PLAN, optimizer);
else {
ProjectRestrictNode prn = (ProjectRestrictNode) this;
if (!(prn.getChildResult() instanceof Optimizable))
updateBestPlanMap(ADD_PLAN, optimizer);
}
if (isBaseTable()) {
DataDictionary dd = getDataDictionary();
TableDescriptor td = getTableDescriptor();
getTrulyTheBestAccessPath().initializeAccessPathName(dd, td);
}
setCostEstimateCost(bestPath.getCostEstimate());
if (optimizerTracingIsOn()) {
getOptimizerTracer().traceRememberingBestAccessPath(bestPath, tableNumber, planType);
}
}
use of org.apache.derby.iapi.sql.compile.AccessPath in project derby by apache.
the class FromTable method nextAccessPath.
/**
* @see Optimizable#nextAccessPath
* @exception StandardException Thrown on error
*/
public boolean nextAccessPath(Optimizer optimizer, OptimizablePredicateList predList, RowOrdering rowOrdering) throws StandardException {
int numStrat = optimizer.getNumberOfJoinStrategies();
boolean found = false;
AccessPath ap = getCurrentAccessPath();
/*
** Most Optimizables have no ordering, so tell the rowOrdering that
** this Optimizable is unordered, if appropriate.
*/
if (userSpecifiedJoinStrategy != null) {
/*
** User specified a join strategy, so we should look at only one
** strategy. If there is a current strategy, we have already
** looked at the strategy, so go back to null.
*/
if (ap.getJoinStrategy() != null) {
ap.setJoinStrategy((JoinStrategy) null);
found = false;
} else {
ap.setJoinStrategy(optimizer.getJoinStrategy(userSpecifiedJoinStrategy));
if (ap.getJoinStrategy() == null) {
throw StandardException.newException(SQLState.LANG_INVALID_JOIN_STRATEGY, userSpecifiedJoinStrategy, getBaseTableName());
}
found = true;
}
} else if (joinStrategyNumber < numStrat) {
/* Step through the join strategies. */
ap.setJoinStrategy(optimizer.getJoinStrategy(joinStrategyNumber));
joinStrategyNumber++;
found = true;
if (optimizerTracingIsOn()) {
getOptimizerTracer().traceConsideringJoinStrategy(ap.getJoinStrategy(), tableNumber);
}
}
/*
** Tell the RowOrdering about columns that are equal to constant
** expressions.
*/
tellRowOrderingAboutConstantColumns(rowOrdering, predList);
return found;
}
use of org.apache.derby.iapi.sql.compile.AccessPath in project derby by apache.
the class GroupByNode method considerPostOptimizeOptimizations.
/**
* Consider any optimizations after the optimizer has chosen a plan.
* Optimizations include:
* o min optimization for scalar aggregates
* o max optimization for scalar aggregates
*
* @param selectHasPredicates true if SELECT containing this
* vector/scalar aggregate has a restriction
*
* @exception StandardException on error
*/
void considerPostOptimizeOptimizations(boolean selectHasPredicates) throws StandardException {
/* Consider the optimization for min with asc index on that column or
* max with desc index on that column:
* o No group by
* o One of:
* o min/max(ColumnReference) is only aggregate && source is
* ordered on the ColumnReference
* o min/max(ConstantNode)
* The optimization of the other way around (min with desc index or
* max with asc index) has the same restrictions with the additional
* temporary restriction of no qualifications at all (because
* we don't have true backward scans).
*/
if (groupingList == null) {
if (aggregates.size() == 1) {
AggregateNode an = aggregates.get(0);
AggregateDefinition ad = an.getAggregateDefinition();
if (ad instanceof MaxMinAggregateDefinition) {
if (an.getOperand() instanceof ColumnReference) {
/* See if the underlying ResultSet tree
* is ordered on the ColumnReference.
*/
ColumnReference[] crs = { (ColumnReference) an.getOperand() };
// Holder list for the FromBaseTable. We expect no more
// than one table, hence initial capacity is 1.
ArrayList<FromBaseTable> fbtHolder = new ArrayList<FromBaseTable>(1);
boolean minMaxOptimizationPossible = isOrderedOn(crs, false, fbtHolder);
if (SanityManager.DEBUG) {
SanityManager.ASSERT(fbtHolder.size() <= 1, "bad number of FromBaseTables returned by isOrderedOn() -- " + fbtHolder.size());
}
if (minMaxOptimizationPossible) {
boolean ascIndex = true;
int colNum = crs[0].getColumnNumber();
/* Check if we have an access path, this will be
* null in a join case (See Beetle 4423,DERBY-3904)
*/
AccessPath accessPath = getTrulyTheBestAccessPath();
if (accessPath == null || accessPath.getConglomerateDescriptor() == null || accessPath.getConglomerateDescriptor().getIndexDescriptor() == null)
return;
IndexDescriptor id = accessPath.getConglomerateDescriptor().getIndexDescriptor();
int[] keyColumns = id.baseColumnPositions();
boolean[] isAscending = id.isAscending();
for (int i = 0; i < keyColumns.length; i++) {
/* in such a query: select min(c3) from
* tab1 where c1 = 2 and c2 = 5, if prefix keys
* have equality operator, then we can still use
* the index. The checking of equality operator
* has been done in isStrictlyOrderedOn.
*/
if (colNum == keyColumns[i]) {
if (!isAscending[i])
ascIndex = false;
break;
}
}
FromBaseTable fbt = fbtHolder.get(0);
MaxMinAggregateDefinition temp = (MaxMinAggregateDefinition) ad;
if (((!temp.isMax()) && ascIndex) || ((temp.isMax()) && !ascIndex)) {
fbt.disableBulkFetch();
singleInputRowOptimization = true;
} else /*
** Max optimization with asc index or min with
** desc index is currently more
** restrictive than otherwise.
** We are getting the store to return the last
** row from an index (for the time being, the
** store cannot do real backward scans). SO
** we cannot do this optimization if we have
** any predicates at all.
*/
if (!selectHasPredicates && ((temp.isMax() && ascIndex) || (!temp.isMax() && !ascIndex))) {
fbt.disableBulkFetch();
fbt.doSpecialMaxScan();
singleInputRowOptimization = true;
}
}
} else if (an.getOperand() instanceof ConstantNode) {
singleInputRowOptimization = true;
}
}
}
}
}
use of org.apache.derby.iapi.sql.compile.AccessPath in project derby by apache.
the class XMLOptTrace method formatPlanSummary.
/**
* <p>
* Produce a string representation of the plan being considered now.
* The string has the following grammar:
* </p>
*
* <pre>
* join :== factor OP factor
*
* OP :== "*" | "#"
*
* factor :== factor | conglomerateName
* </pre>
*/
private String formatPlanSummary(int[] planOrder, int planType) {
try {
OptimizerPlan plan = null;
StringBuilder buffer = new StringBuilder();
boolean avoidSort = (planType == Optimizer.SORT_AVOIDANCE_PLAN);
// a negative optimizable number indicates the end of the plan
int planLength = 0;
for (; planLength < planOrder.length; planLength++) {
if (planOrder[planLength] < 0) {
break;
}
}
for (int i = 0; i < planLength; i++) {
int listIndex = planOrder[i];
if (listIndex >= _currentQueryBlock.optimizableList.size()) {
// should never happen!
buffer.append("{ UNKNOWN LIST INDEX " + listIndex + " } ");
continue;
}
Optimizable optimizable = _currentQueryBlock.optimizableList.getOptimizable(listIndex);
AccessPath ap = avoidSort ? optimizable.getBestSortAvoidancePath() : optimizable.getBestAccessPath();
JoinStrategy js = ap.getJoinStrategy();
UniqueTupleDescriptor utd = OptimizerImpl.isTableFunction(optimizable) ? ((StaticMethodCallNode) ((FromVTI) ((ProjectRestrictNode) optimizable).getChildResult()).getMethodCall()).ad : ap.getConglomerateDescriptor();
OptimizerPlan current = (utd == null) ? new OptimizerPlan.DeadEnd(getOptimizableName(optimizable).toString()) : OptimizerPlan.makeRowSource(utd, _lcc.getDataDictionary());
if (plan != null) {
current = new OptimizerPlan.Join(js, plan, current);
}
plan = current;
}
return plan.toString();
} catch (Exception e) {
return e.getMessage();
}
}
Aggregations