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; }
Join * AppliedStatMan::formJoinExprWithCANodeSets( const CANodeIdSet & leftNodeSet, const CANodeIdSet & rightNodeSet, EstLogPropSharedPtr& inLP, const ValueIdSet * joinPreds, const NABoolean cacheable) { EstLogPropSharedPtr leftEstLogProp = NULL; EstLogPropSharedPtr rightEstLogProp = NULL; CANodeIdSet * inputNodeSet = NULL; if (inLP->isCacheable()) { inputNodeSet = inLP->getNodeSet(); // if inLP are cacheable these should have a nodeSet attached // if it is not for some reason, assert in debug mode. In release // mode do not look for properties in ASM cache, instead get them // from group attr cache. if (inputNodeSet == NULL) { CCMPASSERT(inputNodeSet != NULL); inLP->setCacheableFlag(FALSE); } } CANodeIdSet commonNodeSet = leftNodeSet; commonNodeSet.intersectSet(rightNodeSet); // remove CANodeIds which are common to both left and the right children // from the child, whose estLogProps are not cached. If the estLogProps // of both children are not cached, then remove it from the child which // has a larger CANodeIdSet associated with it. CANodeIdSet tempLeftNodeSet = leftNodeSet; CANodeIdSet tempRightNodeSet = rightNodeSet; if (commonNodeSet.entries() > 0) { if (lookup(leftNodeSet)) tempRightNodeSet.subtractSet(commonNodeSet); else if (lookup(rightNodeSet)) tempLeftNodeSet.subtractSet(commonNodeSet); else if (leftNodeSet.entries() > rightNodeSet.entries()) tempLeftNodeSet.subtractSet(commonNodeSet); else tempRightNodeSet.subtractSet(commonNodeSet); } // get the estLogProps for the left and the right child. // If these are not in the cache, then synthesize them incrementally // starting from the left most JBBC in the JBBSubset if (inputNodeSet) { // leftEstLogProp cached? CANodeIdSet combinedNodeSetWithInput = tempLeftNodeSet; combinedNodeSetWithInput.insert(*inputNodeSet); leftEstLogProp = getCachedStatistics(&combinedNodeSetWithInput); combinedNodeSetWithInput = tempRightNodeSet; combinedNodeSetWithInput.insert(*inputNodeSet); rightEstLogProp = getCachedStatistics(&combinedNodeSetWithInput); } if (leftEstLogProp == NULL) leftEstLogProp = synthesizeLogProp(&tempLeftNodeSet, inLP); // if the estimate logical properties have been computed for non-cacheable // inLP, then these would not contain nodeSet. But we do need the nodeSet // to compute potential output values. Hence we shall add this now if (!leftEstLogProp->getNodeSet()) { CANodeIdSet * copyLeftNodeSet = new (STMTHEAP) CANodeIdSet (tempLeftNodeSet); leftEstLogProp->setNodeSet(copyLeftNodeSet); } if (rightEstLogProp == NULL) rightEstLogProp = synthesizeLogProp(&tempRightNodeSet, inLP); if (!rightEstLogProp->getNodeSet()) { CANodeIdSet * copyRightNodeSet = new (STMTHEAP) CANodeIdSet (tempRightNodeSet); rightEstLogProp->setNodeSet(copyRightNodeSet); } // Now form the join expressions with these EstLogProp, // inLP and the joinPred will be same as those for which the // estLogProp are to be synthesized. Cacheable flag would depend // on whether left, right and the outer child are caheable, or // if the join is on all columns or not // Since the join expression consists of the left and the right // JBBSubsets, the JBBSubset for this Join expression would be // the superset of left and right JBBSubset JBBSubset * combinedSet = leftNodeSet.jbbcsToJBBSubset(); combinedSet->addSubset(*(rightNodeSet.jbbcsToJBBSubset())); // Now form the join expressions with these EstLogProp, // inLP and the joinPred will be same as those for which the // estLogProp are to be synthesized. Cacheable flag would depend // on whether left, right and the outer child are ccaheable, or // if the join is on all columns or not return formJoinExprWithEstLogProps(leftEstLogProp, rightEstLogProp, inLP, joinPreds, cacheable, combinedSet); } // AppliedStatMan::formJoinExprWithCANodeSets