MultiJoin::MultiJoin(const JBBSubset & jbbSubset, CollHeap *oHeap) : RelExpr(REL_MULTI_JOIN, NULL, NULL, oHeap) , jbbSubset_(jbbSubset) , childrenMap_(oHeap) , scheduledLSRs_(oHeap) { // Need to initialize the childrenMap // This will set all children to NULL CANodeIdSet jbbcs = jbbSubset_.getJBBCs(); Lng32 index = 0; for (CANodeId x= jbbcs.init(); jbbcs.next(x); jbbcs.advance(x) ) { JBBCExprGroupEntry* entry = new (oHeap) JBBCExprGroupEntry(x, (RelExpr*)NULL, oHeap); childrenMap_.insertAt(index, entry); index++; } lsrC_ = new (oHeap) LSRConfidence(oHeap); #pragma warning (disable : 4018) //warning elimination CMPASSERT (getArity() == jbbcs.entries()); #pragma warning (default : 4018) //warning elimination }
ValueIdSet AppliedStatMan::getPotentialOutputs( const CANodeIdSet & jbbcsNodeSet) { ValueIdSet potentialOutputs; for (CANodeId jbbc = jbbcsNodeSet.init(); jbbcsNodeSet.next(jbbc); jbbcsNodeSet.advance(jbbc)) { if (NodeAnalysis * jbbcNodeAnalysis = jbbc.getNodeAnalysis()) { ValueIdSet outputs; const Join * jbbcParentJoin = jbbcNodeAnalysis->getJBBC()-> getOriginalParentJoin(); if((!jbbcParentJoin) || (jbbcParentJoin && jbbcParentJoin->isInnerNonSemiJoin())) outputs = jbbcNodeAnalysis->getOriginalExpr()->\ getGroupAttr()->getCharacteristicOutputs(); else if (jbbcParentJoin->isLeftJoin()) outputs = jbbcParentJoin->nullInstantiatedOutput(); potentialOutputs.insert(outputs); } } return potentialOutputs; } // AppliedStatMan::getPotentialOutputs
void MvQueryRewriteHandler::dumpAnalysisToFile(QueryAnalysis* qa, RelExpr* expr) { // Dump the QueryAnalysis data to a file. NAString analysisFileName = fileNamePrefix_ + ".analysis"; NAString str; expr->unparse(str, OPTIMIZER_PHASE, MVINFO_FORMAT); str += "\n"; str += qa->getText(); // Add in some stuff to look at join predicates for the JBBCs. str += "Join Predicates\n"; str += "==============="; char buffer[20]; ARRAY(JBB*) jbbs = qa->getJBBs(); for (CollIndex jbbInx = 0; jbbInx < jbbs.entries(); jbbInx++) { JBB* jbb = jbbs[jbbInx]; str_itoa(jbbInx, buffer); ((str += "\nJBB #") += NAString(buffer)) += ":\n"; CANodeIdSet jbbcs = jbb->getJBBCs(); for (CANodeId jbbcId=jbbcs.init(); jbbcs.next(jbbcId); jbbcs.advance(jbbcId) ) { str_itoa(jbbcId, buffer); ((str += "\nJBBC with CANodeId ") += NAString(buffer)) += ":\n"; ValueIdSet joinPreds = jbbcId.getNodeAnalysis()->getJBBC()->getJoinPreds(); str += valueIdSetGetText(joinPreds); if (joinPreds.entries() > 0) { str.append("\n(value ids of predicates are "); NABoolean first = true; for (ValueId jpVid=joinPreds.init(); joinPreds.next(jpVid); joinPreds.advance(jpVid)) { if (first) first = FALSE; else str.append(", "); str_itoa(jpVid, buffer); str.append(buffer); } str.append(")\n"); } } str += '\n'; } dumpToFile(analysisFileName.data(), str.data()); } // dumpAnalysisToFile()
// -------------------------------------------------------------------- // use origExprs from NodeAnalysis to set this MultiJoin childrenMap_ // -------------------------------------------------------------------- void MultiJoin::setChildrenFromOrigExprs(QueryAnalysis * qa) { CollHeap* outHeap = qa->outHeap(); CANodeIdSet jbbcs = jbbSubset_.getJBBCs(); CMPASSERT (qa->getJBBCs().contains(jbbcs)); Lng32 index = 0; for (CANodeId x= jbbcs.init(); jbbcs.next(x); jbbcs.advance(x) ) { JBBCExprGroupEntry* entry = new (outHeap) JBBCExprGroupEntry(x, qa->getNodeAnalysis(x)->getOriginalExpr(), outHeap); childrenMap_.insertAt(index, entry); index++; } return; }
// -------------------------------------------------------------------- // use the input JBBCExprGroupMap to set this MultiJoin childrenMap_ // -------------------------------------------------------------------- void MultiJoin::setChildren(const JBBCExprGroupMap & map) { // everything here goes to statement heap CollHeap* outHeap = CmpCommon::statementHeap(); CANodeIdSet jbbcs = jbbSubset_.getJBBCs(); CMPASSERT (map.getJBBCs().contains(jbbcs)); Lng32 index = 0; for (CANodeId x= jbbcs.init(); jbbcs.next(x); jbbcs.advance(x) ) { JBBCExprGroupEntry* entry = new (outHeap) JBBCExprGroupEntry(x, map.getExprGroupIdOfJBBC(x), outHeap); childrenMap_.insertAt(index, entry); index++; } return; }
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; }
// AppliedStatMan::setupASMCacheForJBB method will be called from // Query::Analyze after connectivity analysis has been done and // empty logical properties have been set. void AppliedStatMan::setupASMCacheForJBB(JBB & jbb) { EstLogPropSharedPtr myEstLogProp; // get all JBBCs of JBB const CANodeIdSet jbbcNodeIdSet = jbb.getMainJBBSubset().getJBBCs(); CANodeId jbbcId; // for all jbbcs for (jbbcId = jbbcNodeIdSet.init(); jbbcNodeIdSet.next(jbbcId); jbbcNodeIdSet.advance(jbbcId)) { if (NodeAnalysis * jbbcNode = jbbcId.getNodeAnalysis()) { // Evaluate local predicates only if it is a table. RelExpr * jbbcExpr = jbbcNode->getOriginalExpr(); if ((jbbcNode->getTableAnalysis() != NULL) && (jbbcExpr->getOperatorType() == REL_SCAN)) { // get the original expression of the jbbc Scan * scanExpr = (Scan *) jbbcExpr; ValueIdSet localPreds = scanExpr->getSelectionPredicates(); // if local predicates have already been computed, then skip if ((localPreds.entries() > 0) || !(lookup(jbbcId))) { // check to see this GA has already been associated with // a logExpr for synthesis. If not, then synthesize // log. expression, and then apply local predicates to it if (NOT scanExpr->getGroupAttr()->existsLogExprForSynthesis()) scanExpr->synthLogProp(); myEstLogProp = getStatsForCANodeId(jbbcId); } } } } // Now do a second traversal of the JBB looking for join reducers for (jbbcId = jbbcNodeIdSet.init(); jbbcNodeIdSet.next(jbbcId); jbbcNodeIdSet.advance(jbbcId)) { // now look for all two way joins for this child if (jbbcId.getNodeAnalysis()) { // get all JBBCs connected to this JBBC, and do a two-way // join with all of them CANodeIdSet connectedNodes = jbbcId.getNodeAnalysis()->\ getJBBC()->getJoinedJBBCs(); for (CANodeId connectedTable = connectedNodes.init(); connectedNodes.next(connectedTable); connectedNodes.advance(connectedTable)) { if (connectedTable.getNodeAnalysis()) { // ASM does not concern itself with the order of the tables, // hence it is possible that the join has already been computed CANodeIdSet tableSet = jbbcId; tableSet.insert(connectedTable); if ((myEstLogProp = getCachedStatistics(&tableSet)) == NULL) { CANodeIdSet setForjbbcId(jbbcId); CANodeIdSet setForConnectedTable(connectedTable); myEstLogProp = joinJBBChildren(setForjbbcId, setForConnectedTable); } } } } } } // AppliedStatMan::setupASMCacheForJBB