예제 #1
0
 public override string ExplainOutput(int depth, ExplainOption option)
 {
     if (output_.Count != 0)
     {
         string r = "Output: " + string.Join(",", output_);
         output_.ForEach(x => r += x.ExplainExprWithSubqueryExpanded(depth, option));
         return(r);
     }
     return(null);
 }
예제 #2
0
        protected string ExplainFilter(Expr filter, int depth, ExplainOption option)
        {
            string r = null;

            if (filter != null)
            {
                // append the subquery plan align with filter
                r  = "Filter: " + filter;
                r += filter.ExplainExprWithSubqueryExpanded(depth, option);
            }
            return(r);
        }
예제 #3
0
        public string Explain(ExplainOption option = null, int depth = 0)
        {
            string r              = null;
            bool   exp_output     = option?.show_output_ ?? true;
            bool   exp_showcost   = option?.show_estCost_ ?? false;
            bool   exp_showactual = !(option is null) && option.mode_ >= ExplainMode.analyze;
            bool   exp_id         = option?.show_id_ ?? false;

            if (!(this is PhysicProfiling) && !(this is PhysicCollect))
            {
                r = Utils.Spaces(depth);
                if (depth == 0)
                {
                    if (exp_showcost && this is PhysicNode phytop)
                    {
                        var memorycost = "";
                        var memory     = phytop.InclusiveMemory();
                        if (memory != 0)
                        {
                            memorycost = $", memory={memory}";
                        }
                        r += $"Total cost: {Math.Truncate(phytop.InclusiveCost() * 100) / 100}{memorycost}\n";
                    }
                }
                else
                {
                    r += "-> ";
                }

                // print line of <nodeName> : <Estimation> <Actual>
                var id = _ + (clone_.Equals("notclone") ? "" : "_" + clone_);
                r += $"{this.GetType().Name}{(exp_id ? " " + id : "")} {ExplainInlineDetails()}";
                if (this is PhysicNode phynode && phynode.profile_ != null)
                {
                    if (exp_showcost)
                    {
                        var incCost    = Math.Truncate(phynode.InclusiveCost() * 100) / 100;
                        var cost       = Math.Truncate(phynode.Cost() * 100) / 100;
                        var memorycost = "";
                        var memory     = phynode.Memory();
                        if (memory != 0)
                        {
                            memorycost = $", memory={memory}";
                        }
                        r += $" (inccost={incCost}, cost={cost}, rows={phynode.logic_.Card()}{memorycost})";
                    }
                    if (exp_showactual)
                    {
                        var profile = phynode.profile_;
                        var loops   = profile.nloops_;
                        if (loops == 1 || loops == 0)
                        {
                            Debug.Assert(loops != 0 || profile.nrows_ == 0);
                            r += $" (actual rows={profile.nrows_})";
                        }
                        else
                        {
                            r += $" (actual rows={profile.nrows_ / loops}, loops={loops})";
                        }
                    }
                }
                r += "\n";
                var details = ExplainMoreDetails(depth, option);

                // print current node's output
                var output = exp_output ? ExplainOutput(depth, option) : null;
                if (output != null)
                {
                    r += Utils.Spaces(depth + 2) + output + "\n";
                }
                if (details != null)
                {
                    // remove the last \n in case the details is a subquery
                    var trailing = "\n";
                    if (details[details.Length - 1] == '\n')
                    {
                        trailing = "";
                    }
                    r += Utils.Spaces(depth + 2) + details + trailing;
                }

                depth += 2;
            }

            // guard against endless plan: 255 is an arbitrary number. Instead of
            // throwing here, we choose to print the plan for debugging.
            //
            if (depth <= 255)
            {
                bool printAsConsumer = false;
                if (!printAsConsumer)
                {
                    children_.ForEach(x => r += x.Explain(option, depth));
                }
            }

            return(r);
        }
예제 #4
0
 public virtual string ExplainMoreDetails(int depth, ExplainOption option) => null;
예제 #5
0
 // print utilities
 public virtual string ExplainOutput(int depth, ExplainOption option) => null;
예제 #6
0
        public string Explain(ExplainOption option = null, int depth = 0)
        {
            string r            = null;
            bool   exp_showcost = option?.show_cost_ ?? false;
            bool   exp_output   = option?.show_output_ ?? true;
            bool   exp_id       = option?.show_id_ ?? false;

            if (!(this is PhysicProfiling) && !(this is PhysicCollect))
            {
                r = Utils.Spaces(depth);
                if (depth == 0)
                {
                    if (exp_showcost && this is PhysicNode phytop)
                    {
                        r += $"Total cost: {Math.Truncate(phytop.InclusiveCost()*100)/100}\n";
                    }
                }
                else
                {
                    r += "-> ";
                }

                // print line of <nodeName> : <Estimation> <Actual>
                r += $"{this.GetType().Name}{(exp_id?" "+_:"")} {ExplainInlineDetails()}";
                var phynode = this as PhysicNode;
                if (phynode != null && phynode.profile_ != null)
                {
                    if (exp_showcost)
                    {
                        var incCost = Math.Truncate(phynode.InclusiveCost() * 100) / 100;
                        var cost    = Math.Truncate(phynode.Cost() * 100) / 100;
                        r += $" (inccost={incCost}, cost={cost}, rows={phynode.logic_.Card()})";
                    }

                    var profile = phynode.profile_;
                    if (profile.nloops_ == 1 || profile.nloops_ == 0)
                    {
                        r += $" (actual rows={profile.nrows_})";
                    }
                    else
                    {
                        r += $" (actual rows={profile.nrows_ / profile.nloops_}, loops={profile.nloops_})";
                    }
                }
                r += "\n";
                var details = ExplainMoreDetails(depth, option);

                // print current node's output
                var output = exp_output ? ExplainOutput(depth, option): null;
                if (output != null)
                {
                    r += Utils.Spaces(depth + 2) + output + "\n";
                }
                if (details != null)
                {
                    // remove the last \n in case the details is a subquery
                    var trailing = "\n";
                    if (details[details.Length - 1] == '\n')
                    {
                        trailing = "";
                    }
                    r += Utils.Spaces(depth + 2) + details + trailing;
                }

                depth += 2;
            }

            // guard against endless plan: 255 is an arbitrary number. Instead of
            // throwing here, we choose to print the plan for debugging.
            //
            if (depth <= 255)
            {
                bool printAsConsumer = false;
                if (!printAsConsumer)
                {
                    children_.ForEach(x => r += x.Explain(option, depth));
                }
            }

            // details of distributed query emulation
            if (this is PhysicGather)
            {
                int nthreads = QueryOption.num_machines_;
                int nshuffle = 0;
                VisitEach(x =>
                {
                    if (x is PhysicRedistribute || x is PhysicBroadcast)
                    {
                        nshuffle++;
                    }
                });
                r += $"\nEmulated {QueryOption.num_machines_} machines distributed run " +
                     $"with {nthreads*(1+nshuffle)} threads\n";
            }
            return(r);
        }
예제 #7
0
 public override string ExplainMoreDetails(int depth, ExplainOption option) => ExplainFilter(filter_, depth, option);