Пример #1
0
        public override CGroupMember Apply(CGroupMember expr)
        {
            LogicJoin a_bc     = expr.logic_ as LogicJoin;
            LogicNode a        = (a_bc.lchild_() as LogicMemoRef).Deref <LogicNode>();
            LogicJoin bc       = (a_bc.rchild_() as LogicMemoRef).Deref <LogicJoin>();
            Expr      bcfilter = bc.filter_;
            var       ab       = new LogicJoin(a_bc.lchild_(), bc.lchild_());
            var       c        = bc.rchild_();
            var       ab_c     = new LogicJoin(ab, c);

            Debug.Assert(!a.LeftReferencesRight(bc));
            if (ab.LeftReferencesRight(c))
            {
                return(expr);
            }

            // pull up all join filters and re-push them back
            Expr allfilters = bcfilter;

            if (a_bc.filter_ != null)
            {
                allfilters = allfilters.AddAndFilter(a_bc.filter_);
            }
            if (allfilters != null)
            {
                var andlist = allfilters.FilterToAndList();
                andlist.RemoveAll(e => ab_c.PushJoinFilter(e));
                if (andlist.Count > 0)
                {
                    ab_c.filter_ = andlist.AndListToExpr();
                }
            }

            // Ideally if there is no cross join in the given plan but cross join
            // in the new plan, we shall return the original plan. However, stop
            // exploration now will prevent generating other promising plans. So
            // we have to return the new plan.
            //
            if (expr.QueryOption().optimize_.memo_disable_crossjoin_)
            {
                if (a_bc.filter_ != null && bcfilter != null)
                {
                    if (ab_c.filter_ is null || ab.filter_ is null)
                    {
                        return(expr);
                    }
                }
            }

            return(new CGroupMember(ab_c, expr.group_));
        }
Пример #2
0
        // classic formula is:
        //   A X B => |A|*|B|/max(dA, dB) where dA,dB are distinct values of joining columns
        // This however does not consider join key distribution. In SQL Server 2014, it introduced
        // histogram join to better the estimation.
        //
        public override ulong LogicJoinCE(LogicJoin node)
        {
            ulong getDistinct(Expr key)
            {
                if (key is ColExpr col)
                {
                    var tr = col.tabRef_;

                    if (tr is FromQueryRef fqr && fqr.MapOutputName(col.colName_) != null)
                    {
                        if (fqr.MapOutputName(col.colName_) is ColExpr ce)
                        {
                            tr = ce.tabRef_;
                        }
                    }

                    if (tr is BaseTableRef btr)
                    {
                        var stats = Catalog.sysstat_.GetColumnStat(btr.relname_, col.colName_);
                        return(stats?.EstDistinct() ?? 0);
                    }
                }
                return(0);
            }

            ulong card;

            node.CreateKeyList();
            var cardl = node.lchild_().Card();
            var cardr = node.rchild_().Card();

            ulong dl = 0, dr = 0, mindlr = 1;

            for (int i = 0; i < node.leftKeys_.Count; i++)
            {
                var lv = node.leftKeys_[i];
                dl = getDistinct(lv);
                var rv = node.rightKeys_[i];
                dr = getDistinct(rv);

                if (node.ops_[i] != "=")
                {
                    mindlr = 0;
                    break;
                }
                mindlr = mindlr * Math.Min(dl, dr);
            }

            if (mindlr != 0)
            {
                card = Math.Max(1, (cardl * cardr) / mindlr);
            }
            else
            {
                // fall back to the old estimator
                card = DefaultEstimate(node);
            }
            return(card);
        }
Пример #3
0
        public override CGroupMember Apply(CGroupMember expr)
        {
            LogicJoin  log = expr.logic_ as LogicJoin;
            var        l   = new PhysicMemoRef(log.lchild_());
            var        r   = new PhysicMemoRef(log.rchild_());
            PhysicNode phy = new PhysicNLJoin(log, l, r);

            return(new CGroupMember(phy, expr.group_));
        }
Пример #4
0
        public override CGroupMember Apply(CGroupMember expr)
        {
            LogicJoin log      = expr.logic_ as LogicJoin;
            var       l        = new PhysicMemoRef(log.lchild_());
            var       r        = new PhysicMemoRef(log.rchild_());
            var       hashjoin = new PhysicHashJoin(log, l, r);

            return(new CGroupMember(hashjoin, expr.group_));
        }
Пример #5
0
        public override CGroupMember Apply(CGroupMember expr)
        {
            LogicJoin join = expr.logic_ as LogicJoin;
            var       l = join.lchild_(); var r = join.rchild_(); var f = join.filter_;

            Debug.Assert(!l.LeftReferencesRight(r));
            if (r.LeftReferencesRight(l))
            {
                return(expr);
            }

            LogicJoin newjoin = new LogicJoin(r, l, f);

            return(new CGroupMember(newjoin, expr.group_));
        }
Пример #6
0
        public override bool Appliable(CGroupMember expr)
        {
            LogicJoin join = expr.logic_ as LogicJoin;

            if (join is null || join is LogicMarkJoin || join is LogicSingleJoin)
            {
                return(false);
            }

            if (join.filter_.FilterHashable())
            {
                var  stmt        = expr.Stmt() as SelectStmt;
                bool lhasSubqCol = stmt.PlanContainsCorrelatedSubquery() &&
                                   TableRef.HasColsUsedBySubquries(join.lchild_().InclusiveTableRefs());
                if (!lhasSubqCol)
                {
                    return(true);
                }
            }
            return(false);
        }