Пример #1
0
//---------------------------------------------------------------------------
//	@function:
//		CPhysicalNLJoin::PppsRequiredNLJoinChild
//
//	@doc:
//		Compute required partition propagation of the n-th child
//
//---------------------------------------------------------------------------
CPartitionPropagationSpec *
CPhysicalNLJoin::PppsRequiredNLJoinChild
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	CPartitionPropagationSpec *pppsRequired,
	ULONG ulChildIndex,
	DrgPdp *, //pdrgpdpCtxt,
	ULONG ulOptReq
	)
{
	GPOS_ASSERT(NULL != pppsRequired);

	if (1 == ulOptReq)
	{
		// request (1): push partition propagation requests to join's children,
		// do not consider possible dynamic partition elimination using join predicate here,
		// this is handled by optimization request (0) below
		return CPhysical::PppsRequiredPushThruNAry(pmp, exprhdl, pppsRequired, ulChildIndex);
	}
	GPOS_ASSERT(0 == ulOptReq);

	CPartIndexMap *ppim = pppsRequired->Ppim();
	CPartFilterMap *ppfm = pppsRequired->Ppfm();

	DrgPul *pdrgpul = ppim->PdrgpulScanIds(pmp);
	
	CPartIndexMap *ppimResult = GPOS_NEW(pmp) CPartIndexMap(pmp);
	CPartFilterMap *ppfmResult = GPOS_NEW(pmp) CPartFilterMap(pmp);

	CPartInfo *ppartinfoOuter = exprhdl.Pdprel(0)->Ppartinfo();

	CColRefSet *pcrsOutputOuter = exprhdl.Pdprel(0)->PcrsOutput();
	CColRefSet *pcrsOutputInner = exprhdl.Pdprel(1)->PcrsOutput();

	const ULONG ulPartIndexIds = pdrgpul->UlLength();
		
	for (ULONG ul = 0; ul < ulPartIndexIds; ul++)
	{
		ULONG ulPartIndexId = *((*pdrgpul)[ul]);
		if (ppfm->FContainsScanId(ulPartIndexId))
		{
			GPOS_ASSERT(NULL != ppfm->Pexpr(ulPartIndexId));
			// a selection-based propagation request pushed from above: do not propagate any
			// further as the join will reduce cardinality and thus may select more partitions
			// for scanning
			continue;
		}
		
		BOOL fOuterPartConsumer = ppartinfoOuter->FContainsScanId(ulPartIndexId);

		// in order to find interesting join predicates that can be used for DPE,
		// one side of the predicate must be the partition key, while the other side must only contain
		// references from the join child that does not have the partition consumer
		CColRefSet *pcrsAllowedRefs = pcrsOutputOuter;
		if (fOuterPartConsumer)
		{
			pcrsAllowedRefs = pcrsOutputInner;
		}

		if (0 == ulChildIndex && fOuterPartConsumer)
		{
			// always push through required partition propagation for consumers on the
			// outer side of the nested loop join
			DrgPpartkeys *pdrgppartkeys = ppartinfoOuter->PdrgppartkeysByScanId(ulPartIndexId);
			GPOS_ASSERT(NULL != pdrgppartkeys);
			pdrgppartkeys->AddRef();

			ppimResult->AddRequiredPartPropagation(ppim, ulPartIndexId, CPartIndexMap::EppraPreservePropagators, pdrgppartkeys);
		}
		else
		{
			// check if there is an interesting condition involving the partition key
			CExpression *pexprScalar = exprhdl.PexprScalarChild(2 /*ulChildIndex*/);
			AddFilterOnPartKey(pmp, true /*fNLJoin*/, pexprScalar, ppim, ppfm, ulChildIndex, ulPartIndexId, fOuterPartConsumer, ppimResult, ppfmResult, pcrsAllowedRefs);
		}
	}
	
	pdrgpul->Release();

	return GPOS_NEW(pmp) CPartitionPropagationSpec(ppimResult, ppfmResult);
}
Пример #2
0
//---------------------------------------------------------------------------
//	@function:
//		CPhysical::PppsRequiredPushThruNAry
//
//	@doc:
//		Helper for pushing required partition propagation to the children of
//		an n-ary operator
//
//---------------------------------------------------------------------------
CPartitionPropagationSpec *
CPhysical::PppsRequiredPushThruNAry
	(
	IMemoryPool *mp,
	CExpressionHandle &exprhdl,
	CPartitionPropagationSpec *pppsReqd,
	ULONG child_index
	)
{
	GPOS_ASSERT(NULL != pppsReqd);


	CPartIndexMap *ppimReqd = pppsReqd->Ppim();
	CPartFilterMap *ppfmReqd = pppsReqd->Ppfm();

	ULongPtrArray *pdrgpul = ppimReqd->PdrgpulScanIds(mp);

	CPartIndexMap *ppimResult = GPOS_NEW(mp) CPartIndexMap(mp);
	CPartFilterMap *ppfmResult = GPOS_NEW(mp) CPartFilterMap(mp);

	const ULONG ulPartIndexIds = pdrgpul->Size();
	const ULONG arity = exprhdl.UlNonScalarChildren();

	// iterate over required part index ids and decide which ones to push to the outer
	// and which to the inner side of the n-ary op
	for (ULONG ul = 0; ul < ulPartIndexIds; ul++)
	{
		ULONG part_idx_id = *((*pdrgpul)[ul]);
		GPOS_ASSERT(ppimReqd->Contains(part_idx_id));

		CBitSet *pbsPartConsumer = GPOS_NEW(mp) CBitSet(mp);
		for (ULONG ulChildIdx = 0; ulChildIdx < arity; ulChildIdx++)
		{
			if (exprhdl.GetRelationalProperties(ulChildIdx)->Ppartinfo()->FContainsScanId(part_idx_id))
			{
				(void) pbsPartConsumer->ExchangeSet(ulChildIdx);
			}
		}

		if (arity == pbsPartConsumer->Size() &&
			COperator::EopPhysicalSequence == exprhdl.Pop()->Eopid() &&
			(*(exprhdl.Pgexpr()))[0]->FHasCTEProducer())
		{
			GPOS_ASSERT(2 == arity);

			// this is a part index id that comes from both sides of a sequence
			// with a CTE producer on the outer side, so pretend that part index
			// id is not defined the inner sides
			pbsPartConsumer->ExchangeClear(1);
		}

		if (!FCanPushPartReqToChild(pbsPartConsumer, child_index))
		{
			// clean up
			pbsPartConsumer->Release();

			continue;
		}

		// clean up
		pbsPartConsumer->Release();

		CPartKeysArray *pdrgppartkeys = exprhdl.GetRelationalProperties(child_index)->Ppartinfo()->PdrgppartkeysByScanId(part_idx_id);
		GPOS_ASSERT(NULL != pdrgppartkeys);
		pdrgppartkeys->AddRef();

		// push requirements to child node
		ppimResult->AddRequiredPartPropagation(ppimReqd, part_idx_id, CPartIndexMap::EppraPreservePropagators, pdrgppartkeys);

		// check if there is a filter on the part index id and propagate that further down
		if (ppfmReqd->FContainsScanId(part_idx_id))
		{
			CExpression *pexpr = ppfmReqd->Pexpr(part_idx_id);
			// if the current child is inner child and the predicate is IsNull check and the parent is outer join,
			// don't push IsNull check predicate to the partition filter.
			// for all the other cases, push the filter down.
			if (!(1 == child_index &&
				CUtils::FScalarNullTest(pexpr) &&
				CUtils::FPhysicalOuterJoin(exprhdl.Pop()))
				)
			{
				pexpr->AddRef();
				ppfmResult->AddPartFilter(mp, part_idx_id, pexpr, NULL /*stats */);
			}
		}
	}

	pdrgpul->Release();

	return GPOS_NEW(mp) CPartitionPropagationSpec(ppimResult, ppfmResult);
}
Пример #3
0
//---------------------------------------------------------------------------
//	@function:
//		CPhysicalHashJoin::PppsRequiredCompute
//
//	@doc:
//		Compute required partition propagation of the n-th child
//
//---------------------------------------------------------------------------
CPartitionPropagationSpec *
CPhysicalHashJoin::PppsRequiredCompute
	(
	IMemoryPool *pmp,
	CExpressionHandle &exprhdl,
	CPartitionPropagationSpec *pppsRequired,
	ULONG ulChildIndex
	)
{
	CPartIndexMap *ppim = pppsRequired->Ppim();
	CPartFilterMap *ppfm = pppsRequired->Ppfm();

	DrgPul *pdrgpul = ppim->PdrgpulScanIds(pmp);

	CPartIndexMap *ppimResult = GPOS_NEW(pmp) CPartIndexMap(pmp);
	CPartFilterMap *ppfmResult = GPOS_NEW(pmp) CPartFilterMap(pmp);

	// get outer partition consumers
	CPartInfo *ppartinfo = exprhdl.Pdprel(0)->Ppartinfo();

	CColRefSet *pcrsOutputOuter = exprhdl.Pdprel(0)->PcrsOutput();
	CColRefSet *pcrsOutputInner = exprhdl.Pdprel(1)->PcrsOutput();

	const ULONG ulPartIndexIds = pdrgpul->UlLength();

	for (ULONG ul = 0; ul < ulPartIndexIds; ul++)
	{
		ULONG ulPartIndexId = *((*pdrgpul)[ul]);

		if (ppfm->FContainsScanId(ulPartIndexId))
		{
			GPOS_ASSERT(NULL != ppfm->Pexpr(ulPartIndexId));
			// a selection-based propagation request pushed from above: do not propagate any
			// further as the join will reduce cardinality and thus may select more partitions
			// for scanning
			continue;
		}
		
		BOOL fOuterPartConsumer = ppartinfo->FContainsScanId(ulPartIndexId);

		// in order to find interesting join predicates that can be used for DPE,
		// one side of the predicate must be the partition key, while the other side must only contain
		// references from the join child that does not have the partition consumer
		CColRefSet *pcrsAllowedRefs = pcrsOutputOuter;
		if (fOuterPartConsumer)
		{
			pcrsAllowedRefs = pcrsOutputInner;
		}

		if (1 == ulChildIndex && !fOuterPartConsumer)
		{
			// always push through required partition propagation for consumers on the
			// inner side of the hash join
			DrgPpartkeys *pdrgppartkeys = exprhdl.Pdprel(1 /*ulChildIndex*/)->Ppartinfo()->PdrgppartkeysByScanId(ulPartIndexId);
			GPOS_ASSERT(NULL != pdrgppartkeys);
			pdrgppartkeys->AddRef();

			ppimResult->AddRequiredPartPropagation(ppim, ulPartIndexId, CPartIndexMap::EppraPreservePropagators, pdrgppartkeys);
		}
		else
		{	
			// look for a filter on the part key
			CExpression *pexprScalar = exprhdl.PexprScalarChild(2 /*ulChildIndex*/);
			AddFilterOnPartKey(pmp, false /*fNLJoin*/, pexprScalar, ppim, ppfm, ulChildIndex, ulPartIndexId, fOuterPartConsumer, ppimResult, ppfmResult, pcrsAllowedRefs);
		}
	}

	pdrgpul->Release();

	return GPOS_NEW(pmp) CPartitionPropagationSpec(ppimResult, ppfmResult);
}