private boolean canPushCrossJoin(QueryMetadataInterface metadata, PlanNode accessNode1, PlanNode accessNode2) throws QueryMetadataException, TeiidComponentException { float cost1 = NewCalculateCostUtil.computeCostForTree(accessNode1, metadata); float cost2 = NewCalculateCostUtil.computeCostForTree(accessNode2, metadata); float acceptableCost = 64; return !((cost1 == NewCalculateCostUtil.UNKNOWN_VALUE || cost2 == NewCalculateCostUtil.UNKNOWN_VALUE || (cost1 > acceptableCost && cost2 > acceptableCost))); }
cost = 0; if (isSingleTable(currentNode) && usesKey(compCrit, metadata)) { return 1; float nextCost = recursiveEstimateCostOfCriteria(childCost, currentNode, critPart, metadata); return UNKNOWN_VALUE; float nextCost = recursiveEstimateCostOfCriteria(childCost, currentNode, ((NotCriteria)crit).getCriteria(), metadata); if (nextCost == UNKNOWN_VALUE){ return childCost; cost = estimatePredicateCost(childCost, currentNode, (PredicateCriteria) crit, metadata);
static boolean updateCardinality(PlanNode node, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException { Float cost = (Float) node.getProperty(NodeConstants.Info.EST_CARDINALITY); // check if already computed boolean updated = false; for (PlanNode child : node.getChildren()) { updated |= updateCardinality(child, metadata); } if(cost == null || updated) { computeNodeCost(node, metadata); return true; } return false; }
public static boolean usesKey(Criteria crit, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException { HashSet<ElementSymbol> elements = new HashSet<ElementSymbol>(); collectElementsOfValidCriteria(crit, elements); return usesKey(elements, metadata); }
/** * Estimate the cost of a selection. This is not easy to do without information * about the value count for each relation attribute. * @param metadata */ private static void estimateSelectNodeCost(PlanNode node, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException { PlanNode child = node.getFirstChild(); float childCost = child.getCardinality(); //Get list of conjuncts Criteria selectCriteria = (Criteria)node.getProperty(NodeConstants.Info.SELECT_CRITERIA); float newCost = recursiveEstimateCostOfCriteria(childCost, node, selectCriteria, metadata); setCardinalityEstimate(node, newCost, true, metadata); }
float independentCardinality = computeCostForTree(independentNode, metadata); float dependentCardinality = computeCostForTree(dependentNode, metadata); float indSymbolNDV = getNDVEstimate(independentNode, metadata, independentCardinality, indElements, true); boolean unknownNDV = false; if (indSymbolNDV == UNKNOWN_VALUE) { LinkedList<PlanNode> targets = determineTargets(dependentNode, metadata, capFinder, rpsc, depExpr, depExpressions); float depTargetCardinality = computeCostForTree(target, metadata); if (depTargetCardinality == UNKNOWN_VALUE) { continue; float depSymbolNDV = getNDVEstimate(target, metadata, depTargetCardinality, depElems, isAccess?true:null); boolean usesKey = usesKey(target, depElems, metadata); if (depSymbolNDV == UNKNOWN_VALUE) { indCardinalityOrig = computeCostForTree(indOrigNode, metadata); indSymbolOrigNDV = getStat(Stat.NDV, indElements, indOrigNode, indCardinalityOrig, metadata); if (indSymbolOrigNDV == UNKNOWN_VALUE) { indSymbolOrigNDV = indCardinalityOrig * indSymbolNDV / independentCardinality; usesIndex = usesKey(depElems, target.getGroups(), metadata, false); float[] estimates = estimateCost(accessNode, setCriteriaBatchSize, usesIndex, depTargetCardinality, indSymbolNDV, dependentCardinality, depSymbolNDV, independentCardinality); if (estimates[1] < 0) { if (dca.expectedCardinality == null) {
estimateSourceNodeCost(node, metadata); break; estimateSelectNodeCost(node, metadata); break; estimateJoinNodeCost(node, metadata); break; estimateNodeCost(node, FrameUtil.findTopCols(node), metadata); break; setCardinalityEstimate(node, 1f, true, metadata); } else { estimateNodeCost(node, (List)node.getProperty(NodeConstants.Info.GROUP_COLS), metadata); setCardinalityEstimate(node, childCost, true, metadata); break; setCardinalityEstimate(node, 0f, true, metadata); break; setCardinalityEstimate(node, childCost, true, metadata); break; estimateSetOpCost(node, metadata); break; setCardinalityEstimate(node, cost, true, metadata);
Collection<ElementSymbol> elems = ElementCollectorVisitor.getElements(indExpr, true); if (cardinality == null) { cardinality = NewCalculateCostUtil.computeCostForTree(indNode, metadata); comp.ndv = NewCalculateCostUtil.getNDVEstimate(indNode, metadata, cardinality, elems, true); if (bound) { if (dca != null) {
ColStats colStats = (ColStats) child.getProperty(Info.EST_COL_STATS); if (colStats != null) { List<? extends Expression> outputCols = getOutputCols(node, metadata); ColStats newColStats = new ColStats(); for (Expression expr : outputCols) { Collection<ElementSymbol> elems =ElementCollectorVisitor.getElements(ex, true); value = new float[3]; value[Stat.NDV.ordinal()] = getStat(Stat.NDV, elems, node, cost, metadata); value[Stat.NDV_HIGH.ordinal()] = getStat(Stat.NDV_HIGH, elems, node, cost, metadata); value[Stat.NNV.ordinal()] = getStat(Stat.NNV, elems, node, cost, metadata); colStats = createColStats(node, metadata, cost); node.setProperty(Info.EST_COL_STATS, colStats); ColStats colStats = createColStats(node, metadata, cost); node.setProperty(Info.EST_COL_STATS, colStats); setCardinalityEstimate(node, new Float(cost), false, metadata);
DependentCostAnalysis dca = NewCalculateCostUtil.computeCostForDepJoin(joinNode, !entry.leftCandidate, metadata, capFinder, context); PlanNode dependentNode = sourceNode; dca = NewCalculateCostUtil.computeCostForDepJoin(joinNode, true, metadata, capFinder, context); if (dca.expectedCardinality != null) { dependentNode = siblingNode; pushCriteria |= markDependent(dependentNode, joinNode, metadata, dca, null, capFinder, context, rules, analysisRecord); } else { float sourceCost = NewCalculateCostUtil.computeCostForTree(sourceNode, metadata); float siblingCost = NewCalculateCostUtil.computeCostForTree(siblingNode, metadata); float sourceNdv = NewCalculateCostUtil.getNDVEstimate(sourceNode, metadata, sourceCost, entry.leftCandidate?leftExpressions:rightExpressions, true); float siblingNdv = NewCalculateCostUtil.getNDVEstimate(siblingNode, metadata, siblingCost, entry.leftCandidate?rightExpressions:leftExpressions, true);
setCardinalityEstimate(node, null, true, metadata); return; float leftNdv = getNDVEstimate(child1, metadata, childCost1, leftExpressions, false); float rightNdv = getNDVEstimate(child2, metadata, childCost2, rightExpressions, false); float leftNdv1 = getNDVEstimate(child1, metadata, childCost1, leftExpressions, true); float rightNdv1 = getNDVEstimate(child2, metadata, childCost2, rightExpressions, true); baseCost = recursiveEstimateCostOfCriteria(baseCost, node, crit, metadata); setCardinalityEstimate(node, cost, true, metadata, leftPercent, rightPercent);
boolean right = true; if (joinNode.getLastChild().getType() == NodeConstants.Types.ACCESS && NewCalculateCostUtil.isSingleTable(joinNode.getLastChild())) { key = NewCalculateCostUtil.getKeyUsed(rightExpressions, null, metadata, null); if (key == null && joinNode.getFirstChild().getType() == NodeConstants.Types.ACCESS && NewCalculateCostUtil.isSingleTable(joinNode.getFirstChild())) { key = NewCalculateCostUtil.getKeyUsed(leftExpressions, null, metadata, null); right = false; boolean pushRight = true; if ((joinType == JoinType.JOIN_INNER || joinType == JoinType.JOIN_LEFT_OUTER) && context != null) { float leftCost = NewCalculateCostUtil.computeCostForTree(joinNode.getFirstChild(), metadata); float rightCost = NewCalculateCostUtil.computeCostForTree(joinNode.getLastChild(), metadata); if (leftCost != NewCalculateCostUtil.UNKNOWN_VALUE && rightCost != NewCalculateCostUtil.UNKNOWN_VALUE && (leftCost > context.getProcessorBatchSize() || rightCost > context.getProcessorBatchSize())) {
@Test public void testProjectLiteral() throws Exception { PlanNode project = NodeFactory.getNewNode(NodeConstants.Types.PROJECT); project.setProperty(Info.PROJECT_COLS, Arrays.asList(new Constant(1))); PlanNode access = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); project.addFirstChild(access); access.setProperty(NodeConstants.Info.EST_CARDINALITY, NewCalculateCostUtil.UNKNOWN_VALUE); float cost = NewCalculateCostUtil.computeCostForTree(project, RealMetadataFactory.example1Cached()); assertTrue(cost == NewCalculateCostUtil.UNKNOWN_VALUE); ColStats colStats = (ColStats)project.getProperty(Info.EST_COL_STATS); assertEquals("{1=[1.0, 1.0, 0.0]}", colStats.toString()); access.setProperty(NodeConstants.Info.EST_CARDINALITY, 5f); NewCalculateCostUtil.updateCardinality(project, RealMetadataFactory.example1Cached()); cost = NewCalculateCostUtil.computeCostForTree(project, RealMetadataFactory.example1Cached()); assertTrue(cost == NewCalculateCostUtil.UNKNOWN_VALUE); colStats = (ColStats)project.getProperty(Info.EST_COL_STATS); assertEquals("{1=[1.0, 1.0, 0.0]}", colStats.toString()); }
/** * @param metadata * @throws QueryMetadataException * @throws TeiidComponentException */ private void estimateCriteriaSelectivity(QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException { for (PlanNode node : criteriaNodes) { Criteria crit = (Criteria)node.getProperty(NodeConstants.Info.SELECT_CRITERIA); float[] baseCosts = new float[] {100, 10000, 1000000}; float filterValue = 0; for (int j = 0; j < baseCosts.length; j++) { float filter = NewCalculateCostUtil.recursiveEstimateCostOfCriteria(baseCosts[j], node, crit, metadata); filterValue += filter/baseCosts[j]; } filterValue /= baseCosts.length; node.setProperty(NodeConstants.Info.EST_SELECTIVITY, new Float(filterValue)); } }
/** * Calculate cost of a node and all children, recursively from the bottom up. * @param node * @param metadata * @return Cost computed at the passed node * @throws QueryMetadataException * @throws TeiidComponentException */ static float computeCostForTree(PlanNode node, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException { updateCardinality(node, metadata); return node.getCardinality(); }
private Float getDepJoinCost(QueryMetadataInterface metadata, CapabilitiesFinder capFinder, CommandContext context, PlanNode indNode, List<PlanNode> applicableCriteria, PlanNode depNode) throws QueryMetadataException, TeiidComponentException, QueryPlannerException { if (depNode.hasBooleanProperty(Info.MAKE_NOT_DEP)) { return null; } float indCost = indNode.getCardinality(); if (indCost == NewCalculateCostUtil.UNKNOWN_VALUE) { return null; } List<Criteria> crits = new ArrayList<Criteria>(applicableCriteria.size()); for (PlanNode planNode : applicableCriteria) { crits.add((Criteria) planNode.getProperty(NodeConstants.Info.SELECT_CRITERIA)); } List<Expression> leftExpressions = new LinkedList<Expression>(); List<Expression> rightExpressions = new LinkedList<Expression>(); RuleChooseJoinStrategy.separateCriteria(indNode.getGroups(), depNode.getGroups(), leftExpressions, rightExpressions, crits, new LinkedList<Criteria>()); if (leftExpressions.isEmpty()) { return null; } return NewCalculateCostUtil.computeCostForDepJoin(indNode, depNode, leftExpressions, rightExpressions, metadata, capFinder, context).expectedCardinality; }
collectElementsOfValidCriteria(iter.next(), elements); first = false; } else { HashSet<ElementSymbol> other = new HashSet<ElementSymbol>(); collectElementsOfValidCriteria(iter.next(), other); elements.retainAll(other);
ColStats colStats = (ColStats) node.getProperty(Info.EST_COL_STATS); if (node.getChildCount() == 0 && colStats == null) { colStats = createColStats(node, metadata, cardinality); } else if (colStats == null) { for (int i = branch; i < node.getChildCount(); i++) {
float independentCardinality = computeCostForTree(independentNode, metadata); float dependentCardinality = computeCostForTree(dependentNode, metadata); float indSymbolNDV = getNDVEstimate(independentNode, metadata, independentCardinality, indElements, true); boolean unknownNDV = false; if (indSymbolNDV == UNKNOWN_VALUE) { LinkedList<PlanNode> targets = determineTargets(dependentNode, metadata, capFinder, rpsc, depExpr, depExpressions); float depTargetCardinality = computeCostForTree(target, metadata); if (depTargetCardinality == UNKNOWN_VALUE) { continue; float depSymbolNDV = getNDVEstimate(target, metadata, depTargetCardinality, depElems, isAccess?true:null); boolean usesKey = usesKey(target, depElems, metadata); if (depSymbolNDV == UNKNOWN_VALUE) { indCardinalityOrig = computeCostForTree(indOrigNode, metadata); indSymbolOrigNDV = getStat(Stat.NDV, indElements, indOrigNode, indCardinalityOrig, metadata); if (indSymbolOrigNDV == UNKNOWN_VALUE) { indSymbolOrigNDV = indCardinalityOrig * indSymbolNDV / independentCardinality; usesIndex = usesKey(depElems, target.getGroups(), metadata, false); float[] estimates = estimateCost(accessNode, setCriteriaBatchSize, usesIndex, depTargetCardinality, indSymbolNDV, dependentCardinality, depSymbolNDV, independentCardinality); if (estimates[1] < 0) { if (dca.expectedCardinality == null) {
estimateSourceNodeCost(node, metadata); break; estimateSelectNodeCost(node, metadata); break; estimateJoinNodeCost(node, metadata); break; estimateNodeCost(node, FrameUtil.findTopCols(node), metadata); break; setCardinalityEstimate(node, 1f, true, metadata); } else { estimateNodeCost(node, (List)node.getProperty(NodeConstants.Info.GROUP_COLS), metadata); setCardinalityEstimate(node, childCost, true, metadata); break; setCardinalityEstimate(node, 0f, true, metadata); break; setCardinalityEstimate(node, childCost, true, metadata); break; estimateSetOpCost(node, metadata); break; setCardinalityEstimate(node, cost, true, metadata);