//--------------------------------------------------------------------------- // @function: // CLogicalInnerIndexApply::PstatsDerive // // @doc: // Derive statistics // //--------------------------------------------------------------------------- IStatistics * CLogicalInnerIndexApply::PstatsDerive ( IMemoryPool *pmp, CExpressionHandle &exprhdl, DrgPstat* // pdrgpstatCtxt ) const { GPOS_ASSERT(EspNone < Esp(exprhdl)); IStatistics *pstatsOuter = exprhdl.Pstats(0); IStatistics *pstatsInner = exprhdl.Pstats(1); CExpression *pexprScalar = exprhdl.PexprScalarChild(2 /*ulChildIndex*/); // join stats of the children DrgPstat *pdrgpstat = GPOS_NEW(pmp) DrgPstat(pmp); pstatsOuter->AddRef(); pdrgpstat->Append(pstatsOuter); pstatsInner->AddRef(); pdrgpstat->Append(pstatsInner); IStatistics *pstats = CStatisticsUtils::PstatsJoinArray(pmp, false /*fOuterJoin*/, pdrgpstat, pexprScalar); pdrgpstat->Release(); return pstats; }
//--------------------------------------------------------------------------- // @function: // CExpressionHandle::CopyStats // // @doc: // Copy stats from attached expression/group expression to local stats // members // //--------------------------------------------------------------------------- void CExpressionHandle::CopyStats() { if (!FStatsDerived()) { // stats of attached expression (or its children) have not been derived yet return; } IStatistics *pstats = NULL; if (NULL != m_pexpr) { pstats = const_cast<IStatistics *>(m_pexpr->Pstats()); } else { GPOS_ASSERT(NULL != m_pgexpr); pstats = m_pgexpr->Pgroup()->Pstats(); } GPOS_ASSERT(NULL != pstats); // attach stats pstats->AddRef(); GPOS_ASSERT(NULL == m_pstats); m_pstats = pstats; // attach child stats GPOS_ASSERT(NULL == m_pdrgpstat); m_pdrgpstat = GPOS_NEW(m_pmp) DrgPstat(m_pmp); const ULONG ulArity = UlArity(); for (ULONG ul = 0; ul < ulArity; ul++) { IStatistics *pstatsChild = NULL; if (NULL != m_pexpr) { pstatsChild = const_cast<IStatistics *>((*m_pexpr)[ul]->Pstats()); } else { pstatsChild = (*m_pgexpr)[ul]->Pstats(); } if (NULL != pstatsChild) { pstatsChild->AddRef(); } else { GPOS_ASSERT(FScalarChild(ul)); // create dummy stats for missing scalar children pstatsChild = CStatistics::PstatsEmpty(m_pmp); } m_pdrgpstat->Append(pstatsChild); } }
//--------------------------------------------------------------------------- // @function: // CExpressionHandle::DeriveRootStats // // @doc: // Stat derivation at root operator where handle is attached // //--------------------------------------------------------------------------- void CExpressionHandle::DeriveRootStats ( DrgPstat *pdrgpstatCtxt ) { GPOS_ASSERT(NULL == m_pstats); CLogical *popLogical = CLogical::PopConvert(Pop()); IStatistics *pstatsRoot = NULL; if (FAttachedToLeafPattern()) { // for leaf patterns extracted from memo, trigger state derivation on origin group GPOS_ASSERT(NULL != m_pexpr); GPOS_ASSERT(NULL != m_pexpr->Pgexpr()); pstatsRoot = m_pexpr->Pgexpr()->Pgroup()->PstatsRecursiveDerive(m_pmp, m_pmp, CReqdPropRelational::Prprel(m_prp), pdrgpstatCtxt); pstatsRoot->AddRef(); } else { // otherwise, derive stats using root operator pstatsRoot = popLogical->PstatsDerive(m_pmp, *this, pdrgpstatCtxt); } GPOS_ASSERT(NULL != pstatsRoot); m_pstats = pstatsRoot; }
//--------------------------------------------------------------------------- // @function: // CGroupExpression::PstatsRecursiveDerive // // @doc: // Derive stats recursively on group expression // //--------------------------------------------------------------------------- IStatistics * CGroupExpression::PstatsRecursiveDerive ( IMemoryPool *, // pmpLocal IMemoryPool *pmpGlobal, CReqdPropRelational *prprel, DrgPstat *pdrgpstatCtxt, BOOL fComputeRootStats ) { GPOS_ASSERT(!Pgroup()->FScalar()); GPOS_ASSERT(!Pgroup()->FImplemented()); GPOS_ASSERT(NULL != pdrgpstatCtxt); GPOS_CHECK_ABORT; // trigger recursive property derivation CExpressionHandle exprhdl(pmpGlobal); exprhdl.Attach(this); exprhdl.DeriveProps(NULL /*pdpctxt*/); // compute required relational properties on child groups exprhdl.ComputeReqdProps(prprel, 0 /*ulOptReq*/); // trigger recursive stat derivation exprhdl.DeriveStats(pdrgpstatCtxt, fComputeRootStats); IStatistics *pstats = exprhdl.Pstats(); if (NULL != pstats) { pstats->AddRef(); } return pstats; }
//--------------------------------------------------------------------------- // @function: // CLogical::PstatsPassThruOuter // // @doc: // Helper for common case of passing through derived stats // //--------------------------------------------------------------------------- IStatistics * CLogical::PstatsPassThruOuter ( CExpressionHandle &exprhdl ) { GPOS_CHECK_ABORT; IStatistics *pstats = exprhdl.Pstats(0); pstats->AddRef(); return pstats; }
//--------------------------------------------------------------------------- // @function: // CPhysicalPartitionSelector::PpfmDerive // // @doc: // Derive partition filter map // //--------------------------------------------------------------------------- CPartFilterMap * CPhysicalPartitionSelector::PpfmDerive ( IMemoryPool *mp, CExpressionHandle &exprhdl ) const { if (!FHasFilter()) { return PpfmPassThruOuter(exprhdl); } CPartFilterMap *ppfm = PpfmDeriveCombineRelational(mp, exprhdl); IStatistics *stats = exprhdl.Pstats(); GPOS_ASSERT(NULL != stats); m_pexprCombinedPredicate->AddRef(); stats->AddRef(); ppfm->AddPartFilter(mp, m_scan_id, m_pexprCombinedPredicate, stats); return ppfm; }
//--------------------------------------------------------------------------- // @function: // CLogicalSelect::PstatsDerive // // @doc: // Derive statistics based on filter predicates // //--------------------------------------------------------------------------- IStatistics * CLogicalSelect::PstatsDerive ( IMemoryPool *pmp, CExpressionHandle &exprhdl, DrgPstat *pdrgpstatCtxt ) const { GPOS_ASSERT(Esp(exprhdl) > EspNone); IStatistics *pstatsChild = exprhdl.Pstats(0); if (exprhdl.Pdpscalar(1 /*ulChildIndex*/)->FHasSubquery()) { // in case of subquery in select predicate, we return child stats pstatsChild->AddRef(); return pstatsChild; } // remove implied predicates from selection condition to avoid cardinality under-estimation CExpression *pexprScalar = exprhdl.PexprScalarChild(1 /*ulChildIndex*/); CExpression *pexprPredicate = CPredicateUtils::PexprRemoveImpliedConjuncts(pmp, pexprScalar, exprhdl); // split selection predicate into local predicate and predicate involving outer references CExpression *pexprLocal = NULL; CExpression *pexprOuterRefs = NULL; // get outer references from expression handle CColRefSet *pcrsOuter = exprhdl.Pdprel()->PcrsOuter(); CPredicateUtils::SeparateOuterRefs(pmp, pexprPredicate, pcrsOuter, &pexprLocal, &pexprOuterRefs); pexprPredicate->Release(); IStatistics *pstats = CStatisticsUtils::PstatsFilter(pmp, exprhdl, pstatsChild, pexprLocal, pexprOuterRefs, pdrgpstatCtxt); pexprLocal->Release(); pexprOuterRefs->Release(); return pstats; }
//--------------------------------------------------------------------------- // @function: // CLogicalLimit::PstatsDerive // // @doc: // Derive statistics based on limit // //--------------------------------------------------------------------------- IStatistics * CLogicalLimit::PstatsDerive ( IMemoryPool *pmp, CExpressionHandle &exprhdl, DrgPstat * // not used ) const { GPOS_ASSERT(Esp(exprhdl) > EspNone); IStatistics *pstatsChild = exprhdl.Pstats(0); CMaxCard maxcard = this->Maxcard(pmp, exprhdl); CDouble dRowsMax = CDouble(maxcard.Ull()); if (pstatsChild->DRows() <= dRowsMax) { pstatsChild->AddRef(); return pstatsChild; } return pstatsChild->PstatsLimit(pmp, dRowsMax); }
//--------------------------------------------------------------------------- // @function: // CExpressionHandle::DeriveCostContextStats // // @doc: // Stats derivation based on required plan properties // //--------------------------------------------------------------------------- void CExpressionHandle::DeriveCostContextStats() { GPOS_ASSERT(NULL != m_pcc); GPOS_ASSERT(NULL == m_pcc->Pstats()); // copy group properties and stats CopyGroupProps(); CopyStats(); if (NULL != m_pstats && !m_pcc->FNeedsNewStats()) { // there is no need to derive stats, // stats are copied from owner group return; } CEnfdPartitionPropagation *pepp = m_pcc->Poc()->Prpp()->Pepp(); COperator *pop = Pop(); if (CUtils::FPhysicalScan(pop) && CPhysicalScan::PopConvert(pop)->FDynamicScan() && !pepp->PpfmDerived()->FEmpty()) { // derive stats on dynamic table scan using stats of part selector CPhysicalScan *popScan = CPhysicalScan::PopConvert(m_pgexpr->Pop()); IStatistics *pstatsDS = popScan->PstatsDerive(m_pmp, *this, m_pcc->Poc()->Prpp(), m_pcc->Poc()->Pdrgpstat()); CRefCount::SafeRelease(m_pstats); m_pstats = pstatsDS; return; } // release current stats since we will derive new stats CRefCount::SafeRelease(m_pstats); m_pstats = NULL; // load stats from child cost context -- these may be different from child groups stats CRefCount::SafeRelease(m_pdrgpstat); m_pdrgpstat = NULL; m_pdrgpstat = GPOS_NEW(m_pmp) DrgPstat(m_pmp); const ULONG ulArity = m_pcc->Pdrgpoc()->UlLength(); for (ULONG ul = 0; ul < ulArity; ul++) { COptimizationContext *pocChild = (*m_pcc->Pdrgpoc())[ul]; CCostContext *pccChild = pocChild->PccBest(); GPOS_ASSERT(NULL != pccChild); GPOS_ASSERT(NULL != pccChild->Pstats()); pccChild->Pstats()->AddRef(); m_pdrgpstat->Append(pccChild->Pstats()); } if (CPhysical::PopConvert(m_pgexpr->Pop())->FPassThruStats()) { GPOS_ASSERT(1 == m_pdrgpstat->UlLength()); // copy stats from first child (*m_pdrgpstat)[0]->AddRef(); m_pstats = (*m_pdrgpstat)[0]; return; } // derive stats using the best logical expression with the same children as attached physical operator CGroupExpression *pgexprForStats = m_pcc->PgexprForStats(); GPOS_ASSERT(NULL != pgexprForStats); CExpressionHandle exprhdl(m_pmp); exprhdl.Attach(pgexprForStats); exprhdl.DeriveProps(NULL /*pdpctxt*/); m_pdrgpstat->AddRef(); exprhdl.m_pdrgpstat = m_pdrgpstat; exprhdl.ComputeReqdProps(m_pcc->Poc()->Prprel(), 0 /*ulOptReq*/); GPOS_ASSERT(NULL == exprhdl.m_pstats); IStatistics *pstats = m_pgexpr->Pgroup()->PstatsCompute(m_pcc->Poc(), exprhdl, pgexprForStats); // copy stats to main handle GPOS_ASSERT(NULL == m_pstats); GPOS_ASSERT(NULL != pstats); pstats->AddRef(); m_pstats = pstats; GPOS_ASSERT(m_pstats != NULL); }
//--------------------------------------------------------------------------- // @function: // CExpressionHandle::DeriveStats // // @doc: // Recursive stat derivation // //--------------------------------------------------------------------------- void CExpressionHandle::DeriveStats ( DrgPstat *pdrgpstatCtxt, BOOL fComputeRootStats ) { GPOS_ASSERT(NULL != pdrgpstatCtxt); GPOS_ASSERT(NULL == m_pdrgpstat); GPOS_ASSERT(NULL == m_pstats); GPOS_ASSERT(NULL != m_pdrgprp); // copy input context DrgPstat *pdrgpstatCurrentCtxt = GPOS_NEW(m_pmp) DrgPstat(m_pmp); CUtils::AddRefAppend<IStatistics, CleanupStats>(pdrgpstatCurrentCtxt, pdrgpstatCtxt); // create array of children stats m_pdrgpstat = GPOS_NEW(m_pmp) DrgPstat(m_pmp); ULONG ulMaxChildRisk = 1; const ULONG ulArity = UlArity(); for (ULONG ul = 0; ul < ulArity; ul++) { // create a new context for outer references used by current child DrgPstat *pdrgpstatChildCtxt = PdrgpstatOuterRefs(pdrgpstatCurrentCtxt, ul); IStatistics *pstats = NULL; if (NULL != Pexpr()) { // derive stats recursively on child expression pstats = (*Pexpr())[ul]->PstatsDerive(Prprel(ul), pdrgpstatChildCtxt); } else { // derive stats recursively on child group pstats = (*Pgexpr())[ul]->PstatsRecursiveDerive(m_pmp, m_pmp, Prprel(ul), pdrgpstatChildCtxt); } GPOS_ASSERT(NULL != pstats); // add child stat to current context pstats->AddRef(); pdrgpstatCurrentCtxt->Append(pstats); pdrgpstatChildCtxt->Release(); // add child stat to children stat array pstats->AddRef(); m_pdrgpstat->Append(pstats); if (pstats->UlStatsEstimationRisk() > ulMaxChildRisk) { ulMaxChildRisk = pstats->UlStatsEstimationRisk(); } } if (fComputeRootStats) { // call stat derivation on operator to compute local stats GPOS_ASSERT(NULL == m_pstats); DeriveRootStats(pdrgpstatCtxt); GPOS_ASSERT(NULL != m_pstats); CLogical *popLogical = CLogical::PopConvert(Pop()); ULONG ulRisk = ulMaxChildRisk; if (CStatisticsUtils::FIncreasesRisk(popLogical)) { ++ulRisk; } m_pstats->SetStatsEstimationRisk(ulRisk); } // clean up current stat context pdrgpstatCurrentCtxt->Release(); }