CostScalar AppliedStatMan::computeJoinReduction( const CANodeIdSet & leftChildren, const CANodeIdSet & rightChildren) { CostScalar result = 0; // get stats for left EstLogPropSharedPtr leftCard = getStatsForCANodeIdSet(leftChildren); // get stats for right EstLogPropSharedPtr rightCard = getStatsForCANodeIdSet(rightChildren); CANodeIdSet jbbcsJoinedToRight; CANodeIdSet allPredecessors; CANodeIdSet allSuccessors; for( CANodeId rChild = rightChildren.init(); rightChildren.next(rChild); rightChildren.advance(rChild)) { JBBC * rChildJBBC = rChild.getNodeAnalysis()->getJBBC(); jbbcsJoinedToRight += rChildJBBC->getJoinedJBBCs(); jbbcsJoinedToRight += rChildJBBC->getPredecessorJBBCs(); allPredecessors += rChildJBBC->getPredecessorJBBCs(); jbbcsJoinedToRight += rChildJBBC->getSuccessorJBBCs(); allSuccessors += rChildJBBC->getSuccessorJBBCs(); } CANodeIdSet dependencyCausingNodesFromLeft = leftChildren; dependencyCausingNodesFromLeft.intersectSet(allPredecessors + allSuccessors); CANodeIdSet leftNodesJoinedToRight = leftChildren; leftNodesJoinedToRight.intersectSet(jbbcsJoinedToRight); if(!leftNodesJoinedToRight.entries()) { result = rightCard->getResultCardinality(); return result; } CANodeIdSet leftSetPredecessors; CANodeIdSet newNodes = leftNodesJoinedToRight; CANodeIdSet nodesConsidered; while(newNodes.entries()) { for( CANodeId lChild = newNodes.init(); newNodes.next(lChild); newNodes.advance(lChild)) { JBBC * lChildJBBC = lChild.getNodeAnalysis()->getJBBC(); leftSetPredecessors += lChildJBBC->getPredecessorJBBCs(); nodesConsidered += lChild; } leftSetPredecessors.intersectSet(leftChildren); newNodes = leftSetPredecessors; newNodes -= nodesConsidered; } leftNodesJoinedToRight += leftSetPredecessors; // for a JBBSubset to be legal it has to have at least one // independent jbbc i.e. a jbbcs connect via a innerNonSemiNonTsjJoin // Assumption: leftChildren represents a legal JBBSubset CANodeIdSet independentJBBCsInLeftNodesJoinedToRight = QueryAnalysis::Instance()->getInnerNonSemiNonTSJJBBCs(); independentJBBCsInLeftNodesJoinedToRight.intersectSet(leftNodesJoinedToRight); if(!independentJBBCsInLeftNodesJoinedToRight.entries()) leftNodesJoinedToRight += leftChildren.jbbcsToJBBSubset()-> getJBBSubsetAnalysis()-> getLargestIndependentNode(); EstLogPropSharedPtr cardLeftNodesJoinedToRight = getStatsForCANodeIdSet(leftNodesJoinedToRight); // All nodes connected via a join CANodeIdSet connectedNodes(leftNodesJoinedToRight); connectedNodes += rightChildren; EstLogPropSharedPtr cardConnectedNodes = joinJBBChildren(leftNodesJoinedToRight,rightChildren); result = cardConnectedNodes->getResultCardinality() / cardLeftNodesJoinedToRight->getResultCardinality(); return result; }
// This method forms the join expression for join on JBBC specified by jbbcId // inputEstLogProp should not be cacheable Join * AppliedStatMan::formJoinExprForJoinOnJBBC( CANodeIdSet jbbSubset, CANodeId jbbcId, const ValueIdSet * jbbcLocalPreds, const ValueIdSet * joinPreds, const EstLogPropSharedPtr& inputEstLogProp, const NABoolean cacheable) { NABoolean origInputIsCacheable = inputEstLogProp->isCacheable(); if(origInputIsCacheable) { inputEstLogProp->setCacheableFlag(FALSE); CCMPASSERT("Expecting Non Cacheable Input"); } RelExpr * jbbcExpr = getExprForCANodeId(jbbcId, inputEstLogProp, jbbcLocalPreds); jbbcExpr->getGroupAttr()->outputLogProp(inputEstLogProp); RelExpr * jbbSubsetExpr = jbbSubset.jbbcsToJBBSubset()->getPreferredJoin(); if(!jbbSubsetExpr) if(jbbSubset.entries()==1) if(!inputEstLogProp->isCacheable()) { inputEstLogProp->setCacheableFlag(TRUE); jbbSubsetExpr = getExprForCANodeId(jbbSubset.getFirst(), inputEstLogProp); inputEstLogProp->setCacheableFlag(FALSE); } else jbbSubsetExpr = getExprForCANodeId(jbbSubset.getFirst(), inputEstLogProp); else { CCMPASSERT("No Subset expression, need at least one entry in set"); } RelExpr * leftChildExpr = jbbSubsetExpr; RelExpr * rightChildExpr = jbbcExpr; GroupAttributes * galeft = jbbSubsetExpr->getGroupAttr(); GroupAttributes * garight = jbbcExpr->getGroupAttr(); // xxx JBBC * jbbc = jbbcId.getNodeAnalysis()->getJBBC(); Join * jbbcParentJoin = jbbc->getOriginalParentJoin(); ValueIdSet leftOuterJoinFilterPreds; Join * joinExpr = NULL; if(jbbcParentJoin) { if(jbbcParentJoin->isSemiJoin()) joinExpr = new STMTHEAP Join(leftChildExpr, rightChildExpr, REL_SEMIJOIN, NULL); if(jbbcParentJoin->isAntiSemiJoin()) joinExpr = new STMTHEAP Join(leftChildExpr, rightChildExpr, REL_ANTI_SEMIJOIN, NULL); if(jbbcParentJoin->isLeftJoin()) { joinExpr = new STMTHEAP Join(leftChildExpr, rightChildExpr, REL_LEFT_JOIN, NULL); leftOuterJoinFilterPreds += jbbc->getLeftJoinFilterPreds(); } if(joinExpr) { joinExpr->setJoinPred(jbbc->getPredsWithPredecessors()); joinExpr->nullInstantiatedOutput().insert(jbbc->nullInstantiatedOutput()); } } if(!joinExpr) { // now form a JoinExpr with these left and right children. joinExpr = new STMTHEAP Join(leftChildExpr, rightChildExpr, REL_JOIN, NULL); } ValueIdSet selPredsAndLOJFilter = leftOuterJoinFilterPreds; selPredsAndLOJFilter += (*joinPreds); joinExpr->setSelectionPredicates(selPredsAndLOJFilter); // set groupAttr of this Join expression GroupAttributes * gaJoin = new STMTHEAP GroupAttributes(); // set required outputs of Join as sum of characteristic // outputs of the left and the right children ValueIdSet requiredOutputs; requiredOutputs.addSet(getPotentialOutputs(jbbSubset)); requiredOutputs.addSet(getPotentialOutputs(jbbcId)); gaJoin->setCharacteristicOutputs(requiredOutputs); // set JBBSubset for this group, if all estLogProps are cacheable. // Else JBBSubset is NULL CANodeIdSet combinedSet = jbbSubset; combinedSet += jbbcId; if (cacheable) gaJoin->getGroupAnalysis()->setLocalJBBView(combinedSet.jbbcsToJBBSubset()); gaJoin->setMinChildEstRowCount(MINOF(garight->getMinChildEstRowCount(), galeft->getMinChildEstRowCount() ) ); // if there are some probes coming into the join // then join type = tsj. if ((inputEstLogProp->getResultCardinality() > 1) || (inputEstLogProp->getColStats().entries() > 1)) { if (cacheable) { CANodeIdSet inputNodeSet = *(inputEstLogProp->getNodeSet()); gaJoin->setCharacteristicInputs(getPotentialOutputs(inputNodeSet)); } } joinExpr->setGroupAttr(gaJoin); gaJoin->setLogExprForSynthesis(joinExpr); joinExpr->synthLogProp(); inputEstLogProp->setCacheableFlag(origInputIsCacheable); return joinExpr; } // AppliedStatMan::formJoinExprForJoinOnJBBC