The Component in the joining process
Beispiel #1
0
        /// <summary>
        /// Deep Copy
        /// </summary>
        /// <param name="component"></param>
        public MatchComponent(MatchComponent component)
        {
            Nodes = component.Nodes;
            EdgeMaterilizedDict        = new Dictionary <MatchEdge, bool>(component.EdgeMaterilizedDict);
            MaterializedNodeSplitCount = new Dictionary <MatchNode, int>(component.MaterializedNodeSplitCount);

            UnmaterializedNodeMapping = new Dictionary <MatchNode, List <MatchEdge> >();
            foreach (var nodeMapping in component.UnmaterializedNodeMapping)
            {
                UnmaterializedNodeMapping[nodeMapping.Key] = new List <MatchEdge>(nodeMapping.Value);
            }

            this.TraversalChain = new List <Tuple <MatchNode, MatchEdge, MatchNode, List <MatchEdge>, List <MatchEdge> > >();
            foreach (var chain in component.TraversalChain)
            {
                this.TraversalChain.Add(new Tuple <MatchNode, MatchEdge, MatchNode, List <MatchEdge>, List <MatchEdge> >(
                                            chain.Item1, chain.Item2, chain.Item3, chain.Item4, chain.Item5));
            }

            NodeToMaterializedEdgesDict = new Dictionary <string, List <Tuple <MatchEdge, MaterializedEdgeType> > >();
            foreach (var nodeMatEdges in component.NodeToMaterializedEdgesDict)
            {
                NodeToMaterializedEdgesDict[nodeMatEdges.Key] = new List <Tuple <MatchEdge, MaterializedEdgeType> >(nodeMatEdges.Value);
            }

            SinkNodeStatisticsDict = new Dictionary <MatchNode, Statistics>();
            foreach (var stat in component.SinkNodeStatisticsDict)
            {
                SinkNodeStatisticsDict[stat.Key] = stat.Value;
            }

            Cardinality = component.Cardinality;
            Cost        = component.Cost;
        }
Beispiel #2
0
        public override List <Tuple <MatchNode, MatchEdge, List <MatchEdge>, List <MatchEdge>, List <MatchEdge> > > GetOptimizedTraversalOrder(ConnectedComponent subGraph)
        {
            if (subGraph.Nodes.Count == 1)
            {
                return
                    (this.GenerateTraversalOrderFromTraversalChain(
                         new List <Tuple <MatchNode, MatchEdge, MatchNode, List <MatchEdge>, List <MatchEdge> > >
                {
                    new Tuple <MatchNode, MatchEdge, MatchNode, List <MatchEdge>, List <MatchEdge> >(
                        subGraph.Nodes.First().Value, null, null, null, null)
                }));
            }

            // If it exists, pick a node without incoming edges as the start point
            List <MatchComponent> componentStates = subGraph.Nodes.Where(node => node.Value.ReverseNeighbors.Count == 0).
                                                    Select(node => new MatchComponent(node.Value)).Take(1).ToList();

            // Otherwise, pick a node randomly as the start point
            if (!componentStates.Any())
            {
                componentStates.Add(new MatchComponent(subGraph.Nodes.First().Value));
            }

            // DP
            while (componentStates.Any())
            {
                List <MatchComponent> nextCompnentStates = new List <MatchComponent>();

                // Iterate on current components
                foreach (MatchComponent curComponent in componentStates)
                {
                    OneHeightTree nodeUnits = this.GetNodeUnits(subGraph, curComponent);
                    if (nodeUnits == null &&
                        curComponent.ActiveNodeCount == subGraph.ActiveNodeCount &&
                        curComponent.EdgeMaterilizedDict.Count(e => e.Value == true) == subGraph.Edges.Count(e => e.Value.IsDanglingEdge == false))
                    {
                        return(this.GenerateTraversalOrderFromTraversalChain(curComponent.TraversalChain));
                    }

                    CandidateJoinUnit candidateUnit = this.GetCandidateUnits2(nodeUnits, curComponent);
                    // Add it to the current component to generate next states
                    MatchComponent newComponent = this.GetNextState(curComponent, candidateUnit);

                    if (nextCompnentStates.Count >= MaxStates)
                    {
                        throw new GraphViewException("This graph pattern is not supported yet.");
                    }

                    nextCompnentStates.Add(newComponent);
                }
                componentStates = nextCompnentStates;
            }

            return(null);
        }
Beispiel #3
0
        /// <summary>
        /// Get a full one height tree with joint edges and unmaterlized edges.
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="component"></param>
        /// <returns></returns>
        private OneHeightTree GetNodeUnits(ConnectedComponent graph, MatchComponent component)
        {
            var useOriginalEdge = new List <OneHeightTree>();
            var useRevEdge      = new List <OneHeightTree>();

            // Return node deinfed in the outer context preferably
            foreach (var node in graph.Nodes.Values.Where(n => n.IsFromOuterContext && !component.Nodes.Contains(n)))
            {
                var remainingEdges = node.Neighbors.Where(e => !component.EdgeMaterilizedDict.ContainsKey(e)).ToList();
                if (component.UnmaterializedNodeMapping.ContainsKey(node) ||
                    remainingEdges.Any(e => component.Nodes.Contains(e.SinkNode)))
                {
                    return(new OneHeightTree
                    {
                        TreeRoot = node,
                        Edges = remainingEdges
                    });
                }
            }

            foreach (var node in graph.Nodes.Values.Where(n => !component.Nodes.Contains(n)))
            {
                var remainingEdges = node.Neighbors.Where(e => !component.EdgeMaterilizedDict.ContainsKey(e)).ToList();
                if (component.UnmaterializedNodeMapping.ContainsKey(node))
                {
                    useOriginalEdge.Add(new OneHeightTree
                    {
                        TreeRoot = node,
                        Edges    = remainingEdges,
                    });
                    break;
                }
                if (remainingEdges.Any(e => component.Nodes.Contains(e.SinkNode)))
                {
                    useRevEdge.Add(new OneHeightTree
                    {
                        TreeRoot = node,
                        Edges    = remainingEdges
                    });
                }
            }

            if (useOriginalEdge.Any())
            {
                return(useOriginalEdge[0]);
            }
            if (useRevEdge.Any())
            {
                return(useRevEdge[0]);
            }
            return(null);
        }
Beispiel #4
0
        internal MatchComponent GetNextState2(MatchComponent curComponent, CandidateJoinUnit candidateTree)
        {
            // Deep copy the component
            var newComponent = new MatchComponent(curComponent);

            // Update component
            UpdateComponent(newComponent, candidateTree);

            // Construct traversal chain and Update join cost
            ConstructTraversalChainAndUpdateCost2(newComponent, candidateTree);

            return(newComponent);
        }
Beispiel #5
0
        private void ConstructTraversalChainAndUpdateCost2(MatchComponent curComponent, CandidateJoinUnit nodeUnitCandidate)
        {
            var inPreMatEdges   = nodeUnitCandidate.PreMatIncomingEdges;
            var inPostMatEdges  = nodeUnitCandidate.PostMatIncomingEdges;
            var outPostMatEdges = nodeUnitCandidate.PostMatOutgoingEdges;

            curComponent.TraversalChain2.Add(
                new Tuple <MatchNode, MatchEdge, MatchNode, List <MatchEdge>, List <MatchEdge> >(
                    inPreMatEdges[0].SourceNode,
                    inPreMatEdges[0],
                    inPreMatEdges[0].SinkNode,
                    outPostMatEdges,
                    inPostMatEdges));
        }
Beispiel #6
0
        /// <summary>
        /// Get a full one height tree with joint edges and unmaterlized edges.
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="component"></param>
        /// <returns></returns>
        private OneHeightTree GetNodeUnits(ConnectedComponent graph, MatchComponent component)
        {
            foreach (MatchNode node in graph.Nodes.Values.Where(n => !component.Nodes.ContainsKey(n.NodeAlias)))
            {
                List <MatchEdge> remainingEdges = node.Neighbors.Where(e => !component.EdgeMaterilizedDict.ContainsKey(e)).ToList();
                if (component.UnmaterializedNodeMapping.ContainsKey(node) ||
                    remainingEdges.Any(e => component.Nodes.ContainsKey(e.SinkNode.NodeAlias)))
                {
                    return(new OneHeightTree
                    {
                        TreeRoot = node,
                        Edges = remainingEdges,
                    });
                }
            }

            return(null);
        }
Beispiel #7
0
        /// <summary>
        /// Transit from current component to the new component in the next state given the Node Unit
        /// </summary>
        /// <param name="candidateTree"></param>
        /// <param name="statisticsCalculator"></param>
        /// <returns></returns>
        public MatchComponent GetNextState(
            CandidateJoinUnit candidateTree,
            IMatchJoinStatisticsCalculator statisticsCalculator,
            GraphMetaData metaData)
        {
            // Deep copy the component
            var newComponent = new MatchComponent(this);

            // Constrcuts join conditions and retrieves join selectivity
            double joinSelectivity;
            double sqlEstimatedJoinSelectivity;
            var    joinCondition = newComponent.ConstructJoinCondition(candidateTree, statisticsCalculator, metaData, out joinSelectivity,
                                                                       out sqlEstimatedJoinSelectivity);

            // Constructs physical join method and join table references
            newComponent.ConstructPhysicalJoinAndUpdateCost(candidateTree, joinCondition,
                                                            joinSelectivity, sqlEstimatedJoinSelectivity, metaData);

            return(newComponent);
        }
Beispiel #8
0
        /// <summary>
        /// Calculate the number used for adjusting the SQL Server estimation in the downsize function.
        /// </summary>
        /// <param name="component"></param>
        /// <param name="joinCondition"></param>
        private static WTableReference AdjustEstimation(MatchComponent component, out WBooleanExpression joinCondition, out double affectedSqlEstimatedSize)
        {
            const int       sizeFactor     = 10;
            int             estimateFactor = 0;
            double          size           = component.Cardinality;
            double          estimatedSize  = component.SqlEstimatedSize;
            double          shrinkSize     = component.RightestTableRefSize;
            WTableReference tableReference = component.TableRef;

            affectedSqlEstimatedSize = 1.0;
            joinCondition            = null;

            if (size > sizeFactor * estimatedSize)
            {
                estimateFactor = (int)Math.Ceiling(size / estimatedSize);
            }
            else if (sizeFactor * size < estimatedSize)
            {
                shrinkSize = 1.0 / (1 - Math.Pow((1 - 1.0 / shrinkSize), 1.5));
                if (estimatedSize < shrinkSize)
                {
                    affectedSqlEstimatedSize /= estimatedSize;
                    estimatedSize             = 1;
                }
                else
                {
                    affectedSqlEstimatedSize /= shrinkSize;
                    estimatedSize            /= shrinkSize;
                }
                estimateFactor = (int)Math.Ceiling(size / estimatedSize);
                joinCondition  = ConstructDownSizeJoinCondition(component.RightestTableAlias);
            }
            if (estimateFactor > 1)
            {
                double affectedUpSize;
                tableReference = ConstructUpSizeTableReference(tableReference, estimateFactor,
                                                               out affectedUpSize);
                affectedSqlEstimatedSize *= affectedUpSize;
            }
            return(tableReference);
        }
Beispiel #9
0
        private void ConstructTraversalChainAndUpdateCost(MatchComponent curComponent, CandidateJoinUnit nodeUnitCandidate)
        {
            List <MatchEdge> inPreMatEdges   = nodeUnitCandidate.PreMatIncomingEdges;
            List <MatchEdge> inPostMatEdges  = nodeUnitCandidate.PostMatIncomingEdges;
            List <MatchEdge> outPostMatEdges = nodeUnitCandidate.PostMatOutgoingEdges;

            //
            // Item1: sourceNode
            // Item2: traversalEdge
            // Item3: sinkNode
            // Item4: backwardingEdges
            // Item5: forwardingEdges
            //
            curComponent.TraversalChain.Add(
                new Tuple <MatchNode, MatchEdge, MatchNode, List <MatchEdge>, List <MatchEdge> >(
                    curComponent.Nodes[inPreMatEdges[0].SourceNode.NodeAlias],
                    inPreMatEdges[0],
                    curComponent.Nodes[inPreMatEdges[0].SinkNode.NodeAlias],
                    outPostMatEdges,
                    inPostMatEdges));
        }
Beispiel #10
0
 /// <summary>
 /// Deep Copy
 /// </summary>
 /// <param name="component"></param>
 public MatchComponent(MatchComponent component)
 {
     Nodes = new HashSet <MatchNode>(component.Nodes);
     EdgeMaterilizedDict        = new Dictionary <MatchEdge, bool>(component.EdgeMaterilizedDict);
     MaterializedNodeSplitCount = new Dictionary <MatchNode, int>(component.MaterializedNodeSplitCount);
     UnmaterializedNodeMapping  = new Dictionary <MatchNode, List <MatchEdge> >();
     foreach (var nodeMapping in component.UnmaterializedNodeMapping)
     {
         UnmaterializedNodeMapping[nodeMapping.Key] = new List <MatchEdge>(nodeMapping.Value);
     }
     SinkNodeStatisticsDict = new Dictionary <MatchNode, Statistics>(component.SinkNodeStatisticsDict);
     TableRef                = component.TableRef;
     Cardinality             = component.Cardinality;
     Cost                    = component.Cost;
     DeltaMemory             = component.DeltaMemory;
     TotalMemory             = component.TotalMemory;
     SqlEstimatedDeltaMemory = component.SqlEstimatedDeltaMemory;
     SqlEstimatedTotalMemory = component.SqlEstimatedTotalMemory;
     SqlEstimatedSize        = component.SqlEstimatedSize;
     RightestTableAlias      = component.RightestTableAlias;
     RightestTableRefSize    = component.RightestTableRefSize;
 }
Beispiel #11
0
 /// <summary>
 /// Deep Copy
 /// </summary>
 /// <param name="component"></param>
 public MatchComponent(MatchComponent component)
 {
     Nodes = new List <MatchNode>(component.Nodes);
     EdgeMaterilizedDict        = new Dictionary <MatchEdge, bool>(component.EdgeMaterilizedDict);
     MaterializedNodeSplitCount = new Dictionary <MatchNode, int>(component.MaterializedNodeSplitCount);
     UnmaterializedNodeMapping  = new Dictionary <MatchNode, List <MatchEdge> >();
     foreach (var nodeMapping in component.UnmaterializedNodeMapping)
     {
         UnmaterializedNodeMapping[nodeMapping.Key] = new List <MatchEdge>(nodeMapping.Value);
     }
     StatisticsDict            = new Dictionary <MatchNode, ColumnStatistics>(component.StatisticsDict);
     TableRef                  = component.TableRef;
     Size                      = component.Size;
     Cost                      = component.Cost;
     DeltaMemory               = component.DeltaMemory;
     TotalMemory               = component.TotalMemory;
     EstimateDeltaMemory       = component.EstimateDeltaMemory;
     EstimateTotalMemory       = component.EstimateTotalMemory;
     EstimateSize              = component.EstimateSize;
     FatherOfRightestTableRef  = component.FatherOfRightestTableRef;
     RightestTableRefSize      = component.RightestTableRefSize;
     FatherListofDownSizeTable = new List <Tuple <WQualifiedJoin, String> >(component.FatherListofDownSizeTable);
     Context                   = component.Context;
 }
Beispiel #12
0
        private CandidateJoinUnit GetCandidateUnits2(OneHeightTree tree, MatchComponent component)
        {
            var revEdgeDict = Graph.ReversedEdgeDict;
            var root        = tree.TreeRoot;

            List <MatchEdge> inEdges;

            component.UnmaterializedNodeMapping.TryGetValue(root, out inEdges);
            var outEdges   = new List <MatchEdge>();
            var unpopEdges = new List <MatchEdge>();

            foreach (var edge in tree.Edges)
            {
                if (component.Nodes.Contains(edge.SinkNode))
                {
                    outEdges.Add(edge);
                }
                else
                {
                    unpopEdges.Add(edge);
                }
            }

            var rawEdges   = new Dictionary <string, Tuple <MatchEdge, EdgeDir> >();
            var extInEdges = new Dictionary <string, MatchEdge>();

            if (inEdges != null)
            {
                rawEdges = inEdges.ToDictionary(edge => edge.EdgeAlias,
                                                edge => new Tuple <MatchEdge, EdgeDir>(edge, EdgeDir.In));
                extInEdges = inEdges.ToDictionary(edge => edge.EdgeAlias);
            }
            foreach (var edge in outEdges)
            {
                var key = edge.EdgeAlias;
                rawEdges.Add(key, new Tuple <MatchEdge, EdgeDir>(edge, EdgeDir.Out));
                extInEdges.Add(key, revEdgeDict[key]);
            }

            if (extInEdges.Any())
            {
                var firstEdge = extInEdges.FirstOrDefault(e => e.Value.IsReversed == false);
                if (firstEdge.Value == null)
                {
                    firstEdge = extInEdges.First();
                }
                var preMatInEdges = new Dictionary <string, MatchEdge>
                {
                    { firstEdge.Key, firstEdge.Value }
                };

                var postMatEdges = rawEdges.Where(entry => !preMatInEdges.ContainsKey(entry.Key))
                                   .Select(entry => entry.Value).ToList();
                // Both edge will be forced to choose the incoming direction type
                var postMatIncomingEdges = postMatEdges.Where(entry => entry.Item2 == EdgeDir.In || (entry.Item2 == EdgeDir.Out && entry.Item1.EdgeType == WEdgeType.BothEdge))
                                           .Select(entry => (entry.Item2 == EdgeDir.In ? entry.Item1 : revEdgeDict[entry.Item1.EdgeAlias])).ToList();
                var postMatOutgoingEdges = postMatEdges.Where(entry => entry.Item2 == EdgeDir.Out && entry.Item1.EdgeType != WEdgeType.BothEdge)
                                           .Select(entry => entry.Item1).ToList();

                return(new CandidateJoinUnit
                {
                    TreeRoot = root,
                    PreMatIncomingEdges = preMatInEdges.Select(entry => entry.Value).ToList(),
                    PreMatOutgoingEdges = new List <MatchEdge>(),
                    PostMatIncomingEdges = postMatIncomingEdges,
                    PostMatOutgoingEdges = postMatOutgoingEdges,
                    UnmaterializedEdges = unpopEdges,
                });
            }
            else
            {
                throw new GraphViewException("This graph pattern is not yet supported.");
            }
        }
Beispiel #13
0
        /// <summary>
        /// Calculate the number used for adjusting the SQL Server estimation in the downsize function.
        /// </summary>
        /// <param name="component"></param>
        /// <param name="matEdges"></param>
        /// <param name="joinCondition"></param>
        private static WTableReference AdjustEstimation(MatchComponent component, List<MatchEdge> matEdges, out WBooleanExpression joinCondition, out double affectedSqlEstimatedSize)
        {
            const int sizeFactor = 10;
            int estimateFactor = 0;
            double size = component.Cardinality*
                          matEdges.Select(e => e.AverageDegree).Aggregate(1.0, (cur, next) => cur*next);
            double estimatedSize = component.SqlEstimatedSize * Math.Pow(1000, matEdges.Count);
            double shrinkSize = component.RightestTableRefSize;
            WTableReference tableReference = component.TableRef;
            affectedSqlEstimatedSize = 1.0;
            joinCondition = null;

            if (size > sizeFactor*estimatedSize)
            {
                estimateFactor = (int)Math.Ceiling(size / estimatedSize);
            }
            else if (sizeFactor*size < estimatedSize)
            {
                shrinkSize = 1.0/(1 - Math.Pow((1 - 1.0/shrinkSize), 1.5));
                if (estimatedSize < shrinkSize)
                {
                    affectedSqlEstimatedSize /= estimatedSize;
                    estimatedSize = 1;
                }
                else
                {
                    affectedSqlEstimatedSize /= shrinkSize;
                    estimatedSize /= shrinkSize;
                }
                estimateFactor = (int) Math.Ceiling(size/estimatedSize);
                joinCondition = ConstructDownSizeJoinCondition(component.RightestTableAlias);
            }
            if (estimateFactor > 1)
            {
                double affectedUpSize;
                tableReference = ConstructUpSizeTableReference(tableReference, estimateFactor,
                    out affectedUpSize);
                affectedSqlEstimatedSize *= affectedUpSize;
            }
            return tableReference;
        }
Beispiel #14
0
 /// <summary>
 /// Deep Copy
 /// </summary>
 /// <param name="component"></param>
 public MatchComponent(MatchComponent component)
 {
     Nodes = new HashSet<MatchNode>(component.Nodes);
     EdgeMaterilizedDict = new Dictionary<MatchEdge, bool>(component.EdgeMaterilizedDict);
     MaterializedNodeSplitCount = new Dictionary<MatchNode, int>(component.MaterializedNodeSplitCount);
     UnmaterializedNodeMapping = new Dictionary<MatchNode, List<MatchEdge>>();
     foreach (var nodeMapping in component.UnmaterializedNodeMapping)
     {
         UnmaterializedNodeMapping[nodeMapping.Key] = new List<MatchEdge>(nodeMapping.Value);
     }
     SinkNodeStatisticsDict = new Dictionary<MatchNode, Statistics>(component.SinkNodeStatisticsDict);
     TableRef = component.TableRef;
     LastPostMatEdgeAlias = component.LastPostMatEdgeAlias;
     LastJoinPostMatEdgesCount = component.LastJoinPostMatEdgesCount;
     LastJoinSqlEstCardinality = component.LastJoinSqlEstCardinality;
     LastJoinHint = component.LastJoinHint;
     LastTable = component.LastTable;
     Cardinality = component.Cardinality;
     Cost = component.Cost;
     DeltaMemory = component.DeltaMemory;
     TotalMemory = component.TotalMemory;
     SqlEstimatedDeltaMemory = component.SqlEstimatedDeltaMemory;
     SqlEstimatedTotalMemory = component.SqlEstimatedTotalMemory;
     SqlEstimatedSize = component.SqlEstimatedSize;
     RightestTableAlias = component.RightestTableAlias;
     RightestTableRefSize = component.RightestTableRefSize;
     LastTableAlias = component.LastTableAlias;
     WhereCondition = ObjectExtensions.Copy(component.WhereCondition);
 }
Beispiel #15
0
        /// <summary>
        /// Calculate the number used for adjusting the SQL Server estimation in the downsize function.
        /// </summary>
        /// <param name="component"></param>
        /// <param name="joinCondition"></param>
        private static WTableReference AdjustEstimation(MatchComponent component, out WBooleanExpression joinCondition, out double affectedSqlEstimatedSize)
        {
            const int sizeFactor = 10;
            int estimateFactor = 0;
            double size = component.Cardinality;
            double estimatedSize = component.SqlEstimatedSize;
            double shrinkSize = component.RightestTableRefSize;
            WTableReference tableReference = component.TableRef;
            affectedSqlEstimatedSize = 1.0;
            joinCondition = null;
 
            if (size > sizeFactor*estimatedSize)
            {
                estimateFactor = (int)Math.Ceiling(size / estimatedSize);
            }
            else if (sizeFactor*size < estimatedSize)
            {
                shrinkSize = 1.0/(1 - Math.Pow((1 - 1.0/shrinkSize), 1.5));
                if (estimatedSize < shrinkSize)
                {
                    affectedSqlEstimatedSize /= estimatedSize;
                    estimatedSize = 1;
                }
                else
                {
                    affectedSqlEstimatedSize /= shrinkSize;
                    estimatedSize /= shrinkSize;
                }
                estimateFactor = (int) Math.Ceiling(size/estimatedSize);
                joinCondition = ConstructDownSizeJoinCondition(component.RightestTableAlias);
            }
            if (estimateFactor > 1)
            {
                double affectedUpSize;
                tableReference = ConstructUpSizeTableReference(tableReference, estimateFactor,
                    out affectedUpSize);
                affectedSqlEstimatedSize *= affectedUpSize;
            }
            return tableReference;
        }
Beispiel #16
0
        private void ConstructTraversalChainAndUpdateCost(MatchComponent curComponent, CandidateJoinUnit nodeUnitCandidate)
        {
            var inPreMatEdges = nodeUnitCandidate.PreMatIncomingEdges;

            curComponent.TraversalChain.Add(new Tuple <MatchNode, MatchEdge>(inPreMatEdges[0].SourceNode, inPreMatEdges[0]));
        }
Beispiel #17
0
 /// <summary>
 /// Deep Copy
 /// </summary>
 /// <param name="component"></param>
 public MatchComponent(MatchComponent component)
 {
     Nodes = new List<MatchNode>(component.Nodes);
     EdgeMaterilizedDict = new Dictionary<MatchEdge, bool>(component.EdgeMaterilizedDict);
     MaterializedNodeSplitCount = new Dictionary<MatchNode, int>(component.MaterializedNodeSplitCount);
     UnmaterializedNodeMapping = new Dictionary<MatchNode, List<MatchEdge>>();
     foreach (var nodeMapping in component.UnmaterializedNodeMapping)
     {
         UnmaterializedNodeMapping[nodeMapping.Key] = new List<MatchEdge>(nodeMapping.Value);
     }
     StatisticsDict = new Dictionary<MatchNode, ColumnStatistics>(component.StatisticsDict);
     TableRef = component.TableRef;
     Size = component.Size;
     Cost = component.Cost;
     DeltaMemory = component.DeltaMemory;
     TotalMemory = component.TotalMemory;
     EstimateDeltaMemory = component.EstimateDeltaMemory;
     EstimateTotalMemory = component.EstimateTotalMemory;
     EstimateSize = component.EstimateSize;
     FatherOfRightestTableRef = component.FatherOfRightestTableRef;
     RightestTableRefSize = component.RightestTableRefSize;
     FatherListofDownSizeTable = new List<Tuple<WQualifiedJoin, String>>(component.FatherListofDownSizeTable);
     Context = component.Context;
 }
        /// <summary>
        /// Get a full one height tree with joint edges and unmaterlized edges,
        /// returns a tuple whose first item is the one height tree and the second item
        /// indicates whether the one height tree only joins with the component's materialized
        /// node on its root.
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="component"></param>
        /// <returns></returns>
        public IEnumerable<Tuple<OneHeightTree,bool>> GetNodeUnits(ConnectedComponent graph, MatchComponent component)
        {
            var nodes = graph.Nodes;
            foreach (var node in nodes.Values.Where(e => !graph.IsTailNode[e]))
            {
                //var newJoinUnitList = new List<MatchJoinUnit>()
                bool joint = false;
                var jointEdges = new List<MatchEdge>();
                var nodeEdgeDict = node.Neighbors.ToDictionary(e => e,
                    e => component.EdgeMaterilizedDict.ContainsKey(e));

                // Edge to component node
                foreach (var edge in node.Neighbors.Where(e => !nodeEdgeDict[e]))
                {
                    if (component.Nodes.Contains(edge.SinkNode))
                    {
                        joint = true;
                        nodeEdgeDict[edge] = true;
                        jointEdges.Add(edge);
                    }
                }


                // Component edge to node
                if (!joint && component.UnmaterializedNodeMapping.ContainsKey(node))
                {
                    joint = true;
                }


                // Add unpopulated edges
                var nodeUnpopulatedEdges = nodeEdgeDict.Where(e => !e.Value).Select(e => e.Key).ToList();

                if (joint)
                    yield return new Tuple<OneHeightTree, bool>(new OneHeightTree
                    {
                        TreeRoot = node,
                        MaterializedEdges = jointEdges,
                        UnmaterializedEdges = nodeUnpopulatedEdges,
                    }, false);

                // Single node edge
                else if (nodeUnpopulatedEdges.Count > 0 && component.MaterializedNodeSplitCount.Count > 1 && component.MaterializedNodeSplitCount.ContainsKey(node))
                {
                    yield return new Tuple<OneHeightTree, bool>(new OneHeightTree
                    {
                        TreeRoot = node,
                        MaterializedEdges = jointEdges,
                        UnmaterializedEdges = nodeUnpopulatedEdges,
                    }, true);
                }
            }
        }
Beispiel #19
0
        private CandidateJoinUnit GetCandidateUnits2(OneHeightTree tree, MatchComponent component)
        {
            Dictionary <string, MatchEdge> revEdgeDict = this.Graph.ReversedEdgeDict;
            MatchNode root = tree.TreeRoot;

            List <MatchEdge> inEdges;

            component.UnmaterializedNodeMapping.TryGetValue(root, out inEdges);
            List <MatchEdge> outEdges   = new List <MatchEdge>();
            List <MatchEdge> unpopEdges = new List <MatchEdge>();

            foreach (MatchEdge edge in tree.Edges)
            {
                if (component.Nodes.ContainsKey(edge.SinkNode.NodeAlias))
                {
                    outEdges.Add(edge);
                }
                else
                {
                    unpopEdges.Add(edge);
                }
            }

            Dictionary <string, Tuple <MatchEdge, EdgeDir> > rawEdges = new Dictionary <string, Tuple <MatchEdge, EdgeDir> >();
            Dictionary <string, MatchEdge> extInEdges = new Dictionary <string, MatchEdge>();

            if (inEdges != null)
            {
                rawEdges = inEdges.ToDictionary(edge => edge.EdgeAlias,
                                                edge => new Tuple <MatchEdge, EdgeDir>(edge, EdgeDir.In));
                extInEdges = inEdges.ToDictionary(edge => edge.EdgeAlias);
            }
            foreach (MatchEdge edge in outEdges)
            {
                string key = edge.EdgeAlias;
                rawEdges.Add(key, new Tuple <MatchEdge, EdgeDir>(edge, EdgeDir.Out));
                extInEdges.Add(key, revEdgeDict[key]);
            }

            if (extInEdges.Any())
            {
                KeyValuePair <string, MatchEdge> firstEdge = extInEdges.FirstOrDefault(e => e.Value.IsReversed == false);
                if (firstEdge.Value == null)
                {
                    firstEdge = extInEdges.First();
                }
                Dictionary <string, MatchEdge> preMatInEdges = new Dictionary <string, MatchEdge>
                {
                    { firstEdge.Key, firstEdge.Value }
                };

                List <Tuple <MatchEdge, EdgeDir> > postMatEdges = rawEdges.Where(entry => !preMatInEdges.ContainsKey(entry.Key))
                                                                  .Select(entry => entry.Value).ToList();

                List <MatchEdge> postMatIncomingEdges =
                    postMatEdges.Where(entry => entry.Item2 == EdgeDir.In).Select(entry => entry.Item1).ToList();
                List <MatchEdge> postMatOutgoingEdges =
                    postMatEdges.Where(entry => entry.Item2 == EdgeDir.Out).Select(entry => entry.Item1).ToList();

                return(new CandidateJoinUnit
                {
                    TreeRoot = root,
                    PreMatIncomingEdges = preMatInEdges.Select(entry => entry.Value).ToList(),
                    PreMatOutgoingEdges = new List <MatchEdge>(),
                    PostMatIncomingEdges = postMatIncomingEdges,
                    PostMatOutgoingEdges = postMatOutgoingEdges,
                    UnmaterializedEdges = unpopEdges,
                });
            }
            else
            {
                throw new GraphViewException("This graph pattern is not yet supported.");
            }
        }
Beispiel #20
0
        private void UpdateComponent(MatchComponent curComponent, CandidateJoinUnit candidateTree)
        {
            var nodes = curComponent.Nodes;
            var edgeMaterializedDict      = curComponent.EdgeMaterilizedDict;
            var unmaterializedNodeMapping = curComponent.UnmaterializedNodeMapping;
            var root = candidateTree.TreeRoot;

            if (!nodes.Contains(root))
            {
                nodes.Add(root);
            }
            curComponent.MaterializedNodeSplitCount[root] = 0;

            var inEdges =
                candidateTree.PreMatIncomingEdges.Select(
                    e => new Tuple <MaterializedOrder, MatchEdge>(MaterializedOrder.Pre, e))
                .Union(
                    candidateTree.PostMatIncomingEdges.Select(
                        e => new Tuple <MaterializedOrder, MatchEdge>(MaterializedOrder.Post, e)))
                .ToList();

            var outEdges =
                candidateTree.PreMatOutgoingEdges.Select(
                    e => new Tuple <MaterializedOrder, MatchEdge>(MaterializedOrder.Pre, e))
                .Union(
                    candidateTree.PostMatOutgoingEdges.Select(
                        e => new Tuple <MaterializedOrder, MatchEdge>(MaterializedOrder.Post, e)))
                .ToList();

            if (inEdges.Any())
            {
                unmaterializedNodeMapping.Remove(root);

                foreach (var t in inEdges)
                {
                    var order = t.Item1;
                    var edge  = t.Item2;

                    edgeMaterializedDict[edge] = true;
                }
            }

            if (outEdges.Any())
            {
                foreach (var t in outEdges)
                {
                    var order = t.Item1;
                    var edge  = t.Item2;

                    edgeMaterializedDict[edge] = true;
                }
            }

            var unmatEdges = candidateTree.UnmaterializedEdges;

            foreach (var unmatEdge in unmatEdges)
            {
                edgeMaterializedDict[unmatEdge] = false;;
                var unmatNodeInEdges = unmaterializedNodeMapping.GetOrCreate(unmatEdge.SinkNode);
                unmatNodeInEdges.Add(unmatEdge);
            }
        }
Beispiel #21
0
 /// <summary>
 /// Calculate the number used for adjusting the SQL Server estimation in the downsize function.
 /// </summary>
 /// <param name="component"></param>
 /// <param name="tablfRef"></param>
 /// <param name="joinTable"></param>
 /// <param name="size"></param>
 /// <param name="estimatedSize"></param>
 /// <param name="shrinkSize"></param>
 /// <param name="joinTableTuple"></param>
 private static void AdjustEstimation(
     MatchComponent component,
     WTableReference tablfRef,
     WQualifiedJoin joinTable,
     double size,
     double estimatedSize,
     double shrinkSize,
     Tuple<WQualifiedJoin,String> joinTableTuple)
 {
     const int sizeFactor = 10;
     int estimateFactor = 0;
     if (size > sizeFactor*estimatedSize)
     {
         estimateFactor = (int)Math.Ceiling(size / estimatedSize);
     }
     else if (sizeFactor*size < estimatedSize)
     {
         estimatedSize /= shrinkSize;
         component.EstimateSize /= shrinkSize;
         component.FatherListofDownSizeTable.Add(joinTableTuple);
         estimateFactor = (int) Math.Ceiling(size/estimatedSize);
     }
     if (estimateFactor > 1)
     {
         WTableReference crossApplyTable = tablfRef;
         int pow = (int) (Math.Floor(Math.Log(estimateFactor, 1000)) + 1);
         int adjustValue = (int) Math.Pow(estimateFactor, 1.0/pow);
         while (pow > 0)
         {
             crossApplyTable = new WUnqualifiedJoin
             {
                 FirstTableRef = crossApplyTable,
                 SecondTableRef = new WSchemaObjectFunctionTableReference
                 {
                     SchemaObject = new WSchemaObjectName(
                         new Identifier {Value = "dbo"},
                         new Identifier {Value = "UpSizeFunction"}),
                     Parameters = new List<WScalarExpression>
                     {
                         new WValueExpression {Value = adjustValue.ToString()}
                     },
                     Alias = new Identifier
                     {
                         Value = Path.GetRandomFileName().Replace(".", "").Substring(0, 8),
                     }
                 },
                 UnqualifiedJoinType = UnqualifiedJoinType.CrossApply
             };
             pow--;
             component.EstimateSize *= adjustValue;
         }
         joinTable.FirstTableRef = crossApplyTable;
     }
 }
Beispiel #22
0
        /// <summary>
        /// Calculate join costs and update components using optimal join method & order
        /// </summary>
        /// <param name="nodeUnitCandidate"></param>
        /// <param name="component"></param>
        /// <param name="nodeTable"></param>
        /// <param name="componentTable"></param>
        /// <param name="joinCondition"></param>
        /// <param name="nodeDegrees"></param>
        /// <param name="estimatedNodeUnitSize"></param>
        /// <param name="estimatedSelectivity"></param>
        /// <returns></returns>
        private static WTableReference GetPlanAndUpdateCost(
            OneHeightTree nodeUnitCandidate,
            MatchComponent component,
            WTableReference nodeTable,
            WTableReference componentTable,
            WBooleanExpression joinCondition,
            double nodeDegrees,
            double joinSelectivity,
            double estimatedNodeUnitSize,
            double estimatedSelectivity)
        {
            var nodeUnitSize = nodeUnitCandidate.TreeRoot.EstimatedRows * nodeDegrees;
            var componentSize = component.Size;
            var estimatedCompSize = component.EstimateSize;
            var cost = nodeUnitSize + componentSize;
            //var joinSelectivity =
            //    nodeWithJoinMapping.SelectivityProduct;
                //nodeWithJoinMapping.ExponentialSelevtivityProduct;
            
            WQualifiedJoin joinTable = new WQualifiedJoin
            {
                FirstTableRef = componentTable,
                SecondTableRef = nodeTable,
                JoinCondition = joinCondition,
                QualifiedJoinType = QualifiedJoinType.Inner,
                JoinHint = JoinHint.Hash
            };

            var node = nodeUnitCandidate.TreeRoot;

            // If the node is already in the component, then only multiply the degree to get the size
            double nodeUnitActualSize;


            if (component.MaterializedNodeSplitCount[node] > 0)
            {
                nodeUnitActualSize = nodeDegrees;
                var cEstEdge = Math.Pow(1000, component.EdgeMaterilizedDict.Count(e=>!e.Value));
                var cSize = component.EstimateSize/cEstEdge;
                var nSize = node.EstimatedRows;
                if (nSize > cSize)
                {
                    component.EstimateSize = estimatedNodeUnitSize*cEstEdge*estimatedSelectivity;
                }
                else
                {
                    component.EstimateSize = component.EstimateSize*Math.Pow(1000, nodeUnitCandidate.UnmaterializedEdges.Count)*
                                             estimatedSelectivity;
                }
            }
            else
            {
                nodeUnitActualSize = nodeUnitSize;
                component.EstimateSize *= estimatedNodeUnitSize * estimatedSelectivity;                
            }

           

            //Update Size
            component.Size *= nodeUnitActualSize * joinSelectivity;

            // Update Cost
            component.Cost += cost;

            // Debug
#if DEBUG
            //Trace.Write(component.NodeUnits.Count+" ");
            //foreach (var n in component.NodeUnits.Where(e => e.Key != node.Node.ExposedName))
            //{
            //    Trace.Write(n.Value.NodeRefName);
            //}
            //Trace.Write(component.NodeUnits[node.Node.ExposedName].NodeRefName+" ");
            //Trace.Write(" "+(long)component.Cost+"   "+(long)component.Size);
            //Trace.Write("   ");
            //foreach (var item in component.PopulatedEdgesName)
            //{
            //    Trace.Write(item + " ");
            //}
            //Trace.Write("; ");
            //foreach (var unpopulatedEdge in component.UnpopulatedEdges)
            //{
            //    Trace.Write(unpopulatedEdge.Alias + " ");
            //}
            //Trace.WriteLine("");
#endif

            

            // Update TableRef
            // Only consider the size in the first join
            if (component.MaterializedNodeSplitCount.Count == 2 && component.MaterializedNodeSplitCount.All(e => e.Value == 0))
            {
                var nodeInComp = component.MaterializedNodeSplitCount.Keys.First(e => e != node);
                if (nodeUnitSize < componentSize)
                {
                    joinTable.FirstTableRef = nodeTable;
                    joinTable.SecondTableRef = componentTable;
                    component.TotalMemory = component.DeltaMemory = nodeUnitSize;
                    component.EstimateTotalMemory = component.EstimateDeltaMemory = estimatedNodeUnitSize;
                    component.RightestTableRefSize = nodeInComp.EstimatedRows;
                    component.FatherOfRightestTableRef = new Tuple<WQualifiedJoin, String>(joinTable,
                        component.GetNodeRefName(nodeInComp));
                    AdjustEstimation(component, nodeTable, joinTable, nodeUnitSize, estimatedNodeUnitSize,
                        nodeUnitCandidate.TreeRoot.EstimatedRows, new Tuple<WQualifiedJoin, string>(joinTable, component.GetNodeRefName(node)));
                }
                else
                {
                    component.TotalMemory = component.DeltaMemory = componentSize;
                    component.EstimateTotalMemory = component.EstimateDeltaMemory = component.EstimateSize;
                    component.RightestTableRefSize = nodeUnitCandidate.TreeRoot.EstimatedRows;
                    component.FatherOfRightestTableRef = new Tuple<WQualifiedJoin, String>(joinTable, component.GetNodeRefName(node));
                    AdjustEstimation(component, componentTable, joinTable, componentSize, estimatedCompSize,
                        nodeInComp.EstimatedRows, new Tuple<WQualifiedJoin, string>(joinTable, component.GetNodeRefName(nodeInComp)));

                }
            }
            else
            {
                double sizeFactor = 5;//1000;
                double maxMemory = 1e8;
                double loopJoinInnerThreshold = 10000;
                double loopJoinOuterThreshold = 1000000;


                // Left Deep
                if (componentSize*sizeFactor < nodeUnitSize)
                {
                    var curDeltaMemory = componentSize;
                    component.TotalMemory = component.DeltaMemory + curDeltaMemory;
                    component.DeltaMemory = curDeltaMemory;
                    var curDeltaEstimateMemory = component.EstimateSize;
                    component.EstimateTotalMemory = component.EstimateDeltaMemory + curDeltaEstimateMemory;
                    component.EstimateDeltaMemory = curDeltaEstimateMemory;

                    // Adjust estimation in sql server
                    AdjustEstimation(component, componentTable, joinTable, componentSize, estimatedCompSize,
                        component.RightestTableRefSize, component.FatherOfRightestTableRef);
                    component.FatherOfRightestTableRef = new Tuple<WQualifiedJoin, string>(joinTable, component.GetNodeRefName(node));
                    component.RightestTableRefSize = nodeUnitCandidate.TreeRoot.EstimatedRows;

                }
                else
                {
                    // Loop Join
                    if (
                        //((nodeUnitSize < loopJoinInnerThreshold /*&& componentSize < loopJoinOuterThreshold*/) || component.DeltaMemory + componentSize > maxMemory / 100) &&
                        ((nodeUnitSize < loopJoinInnerThreshold && componentSize < loopJoinOuterThreshold) ||
                         component.DeltaMemory + componentSize > maxMemory) &&
                        nodeUnitCandidate.MaterializedEdges.Count==0)
                    {
                        component.TotalMemory = component.DeltaMemory;
                        component.EstimateTotalMemory = component.EstimateDeltaMemory;
                        joinTable.JoinHint = JoinHint.Loop;
                        component.EstimateSize = estimatedCompSize*estimatedNodeUnitSize/
                                                 nodeUnitCandidate.TreeRoot.TableRowCount;

                    }
                    // Right Deep
                    else
                    {
                        joinTable.FirstTableRef = nodeTable;
                        joinTable.SecondTableRef = componentTable;

                        AdjustEstimation(component, nodeTable, joinTable, nodeUnitSize, estimatedNodeUnitSize,
                            node.EstimatedRows, new Tuple<WQualifiedJoin, string>(joinTable, component.GetNodeRefName(node)));

                        component.TotalMemory += nodeUnitSize;
                        component.DeltaMemory = component.TotalMemory;
                        component.EstimateTotalMemory += estimatedNodeUnitSize;
                        component.EstimateDeltaMemory = component.EstimateTotalMemory;

                    }
                }
            }

            return new WParenthesisTableReference
            {
                Table = joinTable
            };
        }
Beispiel #23
0
        /// <summary>
        /// Transit from current component to the new component in the next state given the Node Unit
        /// </summary>
        /// <param name="candidateTree"></param>
        /// <param name="densityDict"></param>
        /// <param name="subGraph"></param>
        /// <param name="statisticsCalculator"></param>
        /// <returns></returns>
        public MatchComponent GetNextState(
            OneHeightTree candidateTree, 
            Dictionary<string, double> densityDict, 
            IMatchJoinStatisticsCalculator statisticsCalculator)
        {
            var newComponent = new MatchComponent(this);
            var root = candidateTree.TreeRoot;

            WBooleanExpression joinCondition = null;
            string nodeName = "";


            // Update Nodes
            if (newComponent.MaterializedNodeSplitCount.ContainsKey(root))
            {
                newComponent.MaterializedNodeSplitCount[root]++;
                nodeName = newComponent.GetNodeRefName(root);
                joinCondition = new WBooleanComparisonExpression
                {
                    FirstExpr = new WColumnReferenceExpression
                    {
                        ColumnType = ColumnType.Regular,
                        MultiPartIdentifier = new WMultiPartIdentifier(
                            new Identifier {Value = root.RefAlias},
                            new Identifier {Value = "GlobalNodeId"}
                            ),
                    },
                    SecondExpr = new WColumnReferenceExpression
                    {
                        ColumnType = ColumnType.Regular,
                        MultiPartIdentifier = new WMultiPartIdentifier(
                            new Identifier {Value = nodeName},
                            new Identifier {Value = "GlobalNodeId"}
                            ),
                    },
                    ComparisonType = BooleanComparisonType.Equals
                };
            }
            else
            {
                nodeName = root.RefAlias;
                newComponent.Nodes.Add(root);
                newComponent.MaterializedNodeSplitCount[root] = 0;
                newComponent.StatisticsDict[root] = new ColumnStatistics {Selectivity = 1.0/root.TableRowCount};

            }

            // Constructs table reference
            WTableReference nodeTable = new WNamedTableReference
            {
                Alias = new Identifier { Value = nodeName },
                TableObjectName = root.TableObjectName
            };
            WTableReference compTable = newComponent.TableRef;

            // Updates join conditions
            double selectivity = 1.0;
            double degrees = 1.0;
            var DensityCount = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);

            List<MatchEdge> inEdges;
            if (newComponent.UnmaterializedNodeMapping.TryGetValue(root, out inEdges))
            {
                var firstEdge = inEdges.First();
                bool materialized = newComponent.EdgeMaterilizedDict[firstEdge];
                newComponent.UnmaterializedNodeMapping.Remove(root);
                selectivity *= 1.0/root.TableRowCount;

                // Component materialized edge to root
                if (materialized)
                {
                    joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression
                    {
                        FirstExpr = new WColumnReferenceExpression
                        {
                            ColumnType = ColumnType.Regular,
                            MultiPartIdentifier = new WMultiPartIdentifier(
                                new Identifier {Value = firstEdge.EdgeAlias},
                                new Identifier {Value = "Sink"}
                                ),
                        },
                        SecondExpr = new WColumnReferenceExpression
                        {
                            ColumnType = ColumnType.Regular,
                            MultiPartIdentifier = new WMultiPartIdentifier(
                                new Identifier {Value = nodeName},
                                new Identifier {Value = "GlobalNodeId"}
                                )
                        },
                        ComparisonType = BooleanComparisonType.Equals
                    });

                    //var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[root],
                    //    new ColumnStatistics {Selectivity = 1.0/root.TableRowCount});
                    //selectivity *= statistics.Selectivity;
                    //newComponent.StatisticsDict[root] = statistics;

                    if (DensityCount.ContainsKey(root.TableObjectName.ToString()))
                        DensityCount[root.TableObjectName.ToString()]++;
                    else
                        DensityCount[root.TableObjectName.ToString()] = 1;
                }
                // Component unmaterialized edge to root                
                else
                {
                    ColumnStatistics statistics = null;
                    foreach (var edge in inEdges)
                    {
                        // Update component table
                        compTable = SpanTableRef(compTable, edge, newComponent.GetNodeRefName(edge.SourceNode));

                        newComponent.EdgeMaterilizedDict[edge] = true;
                        joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition,
                            new WBooleanComparisonExpression
                            {
                                FirstExpr = new WColumnReferenceExpression
                                {
                                    ColumnType = ColumnType.Regular,
                                    MultiPartIdentifier = new WMultiPartIdentifier(
                                        new Identifier {Value = edge.EdgeAlias},
                                        new Identifier {Value = "Sink"}
                                        ),
                                },
                                SecondExpr = new WColumnReferenceExpression
                                {
                                    ColumnType = ColumnType.Regular,
                                    MultiPartIdentifier = new WMultiPartIdentifier(
                                        new Identifier {Value = nodeName},
                                        new Identifier {Value = "GlobalNodeId"}
                                        )
                                },
                                ComparisonType = BooleanComparisonType.Equals
                            });
                        statistics = ColumnStatistics.UpdateHistogram(statistics,
                            newComponent.Context.GetEdgeStatistics(edge));
                        selectivity *= statistics.Selectivity;

                        
                    }
                    newComponent.StatisticsDict[root] = statistics;

                    if (DensityCount.ContainsKey(root.TableObjectName.ToString()))
                        DensityCount[root.TableObjectName.ToString()]+=inEdges.Count;
                    else
                        DensityCount[root.TableObjectName.ToString()] = inEdges.Count;
                }
            }

            var jointEdges = candidateTree.MaterializedEdges;
            int sinkToSinkCount = 0;
            foreach (var jointEdge in jointEdges)
            {
                // Update node table
                nodeTable = SpanTableRef(nodeTable, jointEdge, nodeName);
                degrees *= jointEdge.AverageDegree;

                newComponent.EdgeMaterilizedDict[jointEdge] = true;
                var sinkNode = jointEdge.SinkNode;
                // Leaf to component materialized node
                if (newComponent.MaterializedNodeSplitCount.ContainsKey(sinkNode))
                {
                    joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition,
                        new WBooleanComparisonExpression
                        {
                            FirstExpr = new WColumnReferenceExpression
                            {
                                ColumnType = ColumnType.Regular,
                                MultiPartIdentifier = new WMultiPartIdentifier(
                                    new Identifier {Value = jointEdge.EdgeAlias},
                                    new Identifier {Value = "Sink"}
                                    ),
                            },
                            SecondExpr = new WColumnReferenceExpression
                            {
                                ColumnType = ColumnType.Regular,
                                MultiPartIdentifier = new WMultiPartIdentifier(
                                    new Identifier {Value = sinkNode.RefAlias},
                                    new Identifier {Value = "GlobalNodeId"}
                                    )
                            },
                            ComparisonType = BooleanComparisonType.Equals
                        });
                    var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[sinkNode],
                        newComponent.Context.GetEdgeStatistics(jointEdge));
                    selectivity *= statistics.Selectivity;
                    newComponent.StatisticsDict[sinkNode] = statistics;

                    if (DensityCount.ContainsKey(sinkNode.TableObjectName.ToString()))
                        DensityCount[sinkNode.TableObjectName.ToString()]++;
                    else
                        DensityCount[sinkNode.TableObjectName.ToString()] = 1;
                }
                // Leaf to component unmaterialized node
                else
                {
                    inEdges = newComponent.UnmaterializedNodeMapping[sinkNode];
                    var firstEdge = inEdges.First();
                    bool materlizedEdge = newComponent.EdgeMaterilizedDict[firstEdge];
                   
                    // Leaf to materialized leaf
                    if (materlizedEdge)
                    {
                        joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition,
                            new WBooleanComparisonExpression
                            {
                                FirstExpr = new WColumnReferenceExpression
                                {
                                    ColumnType = ColumnType.Regular,
                                    MultiPartIdentifier = new WMultiPartIdentifier(
                                        new Identifier {Value = jointEdge.EdgeAlias},
                                        new Identifier {Value = "Sink"}
                                        ),
                                },
                                SecondExpr = new WColumnReferenceExpression
                                {
                                    ColumnType = ColumnType.Regular,
                                    MultiPartIdentifier = new WMultiPartIdentifier(
                                        new Identifier { Value = firstEdge.EdgeAlias},
                                        new Identifier {Value = "Sink"}
                                        )
                                },
                                ComparisonType = BooleanComparisonType.Equals
                            });

                        sinkToSinkCount++;
                        var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[sinkNode],
                            newComponent.Context.GetEdgeStatistics(jointEdge));
                        selectivity *= statistics.Selectivity;
                        newComponent.StatisticsDict[sinkNode] = statistics;
                    }
                    // Leaf to unmaterialized leaf
                    else
                    {
                        ColumnStatistics compSinkNodeStatistics = null;
                        foreach (var inEdge in inEdges)
                        {
                            compTable = SpanTableRef(compTable, inEdge, newComponent.GetNodeRefName(inEdge.SourceNode));
                            newComponent.EdgeMaterilizedDict[inEdge] = true;
                            joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition,
                            new WBooleanComparisonExpression
                            {
                                FirstExpr = new WColumnReferenceExpression
                                {
                                    ColumnType = ColumnType.Regular,
                                    MultiPartIdentifier = new WMultiPartIdentifier(
                                        new Identifier { Value = jointEdge.EdgeAlias },
                                        new Identifier { Value = "Sink" }
                                        ),
                                },
                                SecondExpr = new WColumnReferenceExpression
                                {
                                    ColumnType = ColumnType.Regular,
                                    MultiPartIdentifier = new WMultiPartIdentifier(
                                        new Identifier { Value = inEdge.EdgeAlias },
                                        new Identifier { Value = "Sink" }
                                        )
                                },
                                ComparisonType = BooleanComparisonType.Equals
                            });

                            sinkToSinkCount++;
                            var leafToLeafStatistics = statisticsCalculator.GetLeafToLeafStatistics(jointEdge, inEdge);
                            selectivity *= leafToLeafStatistics.Selectivity;
                            compSinkNodeStatistics =
                                ColumnStatistics.UpdateHistogram(compSinkNodeStatistics,
                                    newComponent.Context.GetEdgeStatistics(inEdge));
                        }
                        newComponent.StatisticsDict[sinkNode] = compSinkNodeStatistics;
                    }
                }
            }

            var unmatEdges = candidateTree.UnmaterializedEdges;
            foreach (var unmatEdge in unmatEdges)
            {
                newComponent.EdgeMaterilizedDict[unmatEdge] = false;
                newComponent.Nodes.Add(unmatEdge.SinkNode);
                var sinkNodeInEdges = newComponent.UnmaterializedNodeMapping.GetOrCreate(unmatEdge.SinkNode);
                sinkNodeInEdges.Add(unmatEdge);
                degrees *= unmatEdge.AverageDegree;

            }

            // Calculate Estimated Join Selectivity & Estimated Node Size
            double estimatedSelectity = 1.0;
            int count = 0;
            bool sinkJoin = false;
            foreach (var item in densityDict.Where(e => DensityCount.ContainsKey(e.Key)))
            {
                var density = item.Value;
                var curJoinCount = DensityCount[item.Key];
                var curJoinSelectitivy = Math.Pow(density, 2 - Math.Pow(2, 1 - curJoinCount));
                if (!sinkJoin && ColumnStatistics.DefaultDensity < density)
                {
                    var curSinkJoinSelectivity = Math.Pow(ColumnStatistics.DefaultDensity,
                        2 - Math.Pow(2, 1 - sinkToSinkCount));
                    estimatedSelectity *= Math.Pow(curSinkJoinSelectivity, Math.Pow(2, -count));
                    count += sinkToSinkCount;
                    sinkJoin = true;
                }
                estimatedSelectity *= Math.Pow(curJoinSelectitivy, Math.Pow(2, -count));
                count += curJoinCount;
            }

            var estimatedNodeUnitSize = root.EstimatedRows*
                                        Math.Pow(1000, candidateTree.MaterializedEdges.Count + candidateTree.UnmaterializedEdges.Count);


            // Update Table Reference
            newComponent.TableRef = GetPlanAndUpdateCost(candidateTree, newComponent, nodeTable, compTable, joinCondition,
                degrees, selectivity, estimatedNodeUnitSize, estimatedSelectity);

            return newComponent;
        }
        public IEnumerable <CandidateJoinUnit> GetCandidateUnits(IEnumerable <OneHeightTree> trees,
                                                                 MatchComponent component, Dictionary <string, MatchEdge> revEdgeDict)
        {
            foreach (var tree in trees)
            {
                //bool singleNode = treeTuple.Item2;
                var root = tree.TreeRoot;

                List <MatchEdge> inEdges;
                component.UnmaterializedNodeMapping.TryGetValue(root, out inEdges);
                var outEdges   = new List <MatchEdge>();
                var unpopEdges = new List <MatchEdge>();
                foreach (var edge in tree.Edges)
                {
                    if (component.Nodes.Contains(edge.SinkNode))
                    {
                        outEdges.Add(edge);
                    }
                    else
                    {
                        unpopEdges.Add(edge);
                    }
                }

                var rawEdges   = new Dictionary <string, Tuple <MatchEdge, EdgeDir> >();
                var extInEdges = new Dictionary <string, MatchEdge>();
                if (inEdges != null)
                {
                    rawEdges = inEdges.ToDictionary(edge => edge.EdgeAlias,
                                                    edge => new Tuple <MatchEdge, EdgeDir>(edge, EdgeDir.In));
                    extInEdges = inEdges.ToDictionary(edge => edge.EdgeAlias);
                }
                foreach (var edge in outEdges)
                {
                    var key = edge.EdgeAlias;
                    rawEdges.Add(key, new Tuple <MatchEdge, EdgeDir>(edge, EdgeDir.Out));
                    if (edge.HasReversedEdge)
                    {
                        extInEdges.Add(key, revEdgeDict[key]);
                    }
                }

                var extOutEdges = outEdges.ToDictionary(edge => edge.EdgeAlias);
                if (inEdges != null)
                {
                    foreach (var key in inEdges.Where(edge => edge.HasReversedEdge).Select(edge => edge.EdgeAlias))
                    {
                        extOutEdges.Add(key, revEdgeDict[key]);
                    }
                }

                var sortedExtInEdges = (from entry in extInEdges
                                        orderby entry.Value.AverageDegree ascending
                                        select entry).ToList();
                var sortedExtOutEdges = (from entry in extOutEdges
                                         orderby entry.Value.AverageDegree ascending
                                         select entry).ToList();

                // plan type 1: A => B, Loop Join, might use Hash if |A|/|B| is too large
                if (sortedExtInEdges.Any())
                {
                    var preMatInEdges = new Dictionary <string, MatchEdge>
                    {
                        { sortedExtInEdges[0].Key, sortedExtInEdges[0].Value }
                    };
                    for (var i = 1; i < sortedExtInEdges.Count; ++i)
                    {
                        if (sortedExtInEdges[i].Value.AverageDegree < 1)
                        {
                            preMatInEdges.Add(sortedExtInEdges[i].Key, sortedExtInEdges[i].Value);
                        }
                    }
                    var postMatEdges =
                        rawEdges.Where(entry => !preMatInEdges.ContainsKey(entry.Key))
                        .Select(entry => entry.Value).ToList();
                    for (var i = 0; i < postMatEdges.Count; ++i)
                    {
                        var t    = postMatEdges[i];
                        var edge = t.Item1;
                        var dir  = t.Item2;
                        if (!edge.HasReversedEdge)
                        {
                            continue;
                        }

                        var revEdge = revEdgeDict[edge.EdgeAlias];
                        if (revEdge.AverageDegree < edge.AverageDegree)
                        {
                            postMatEdges[i] = new Tuple <MatchEdge, EdgeDir>(revEdge,
                                                                             dir == EdgeDir.In ? EdgeDir.Out : EdgeDir.In);
                        }
                    }

                    yield return(new CandidateJoinUnit
                    {
                        TreeRoot = root,
                        PreMatIncomingEdges = preMatInEdges.Select(entry => entry.Value)
                                              .OrderBy(edge => edge.AverageDegree).ToList(),
                        PreMatOutgoingEdges = new List <MatchEdge>(),
                        PostMatIncomingEdges = postMatEdges.Where(entry => entry.Item2 == EdgeDir.In)
                                               .Select(entry => entry.Item1).ToList(),
                        PostMatOutgoingEdges = postMatEdges.Where(entry => entry.Item2 == EdgeDir.Out)
                                               .Select(entry => entry.Item1).ToList(),
                        UnmaterializedEdges = unpopEdges,
                        JoinHint = JoinHint.Loop,
                    });
                }
                // plan type 2: A <= B, Hash join
                else if (sortedExtOutEdges.Any())
                {
                    var preMatOutEdges = new Dictionary <string, MatchEdge>
                    {
                        { sortedExtOutEdges[0].Key, sortedExtOutEdges[0].Value }
                    };
                    for (var i = 1; i < sortedExtOutEdges.Count; ++i)
                    {
                        if (sortedExtOutEdges[i].Value.AverageDegree < 1)
                        {
                            preMatOutEdges.Add(sortedExtOutEdges[i].Key, sortedExtOutEdges[i].Value);
                        }
                    }
                    var postMatEdges =
                        rawEdges.Where(entry => !preMatOutEdges.ContainsKey(entry.Key))
                        .Select(entry => entry.Value).ToList();
                    for (var i = 0; i < postMatEdges.Count; ++i)
                    {
                        var t    = postMatEdges[i];
                        var edge = t.Item1;
                        var dir  = t.Item2;
                        if (!edge.HasReversedEdge)
                        {
                            continue;
                        }

                        var revEdge = revEdgeDict[edge.EdgeAlias];
                        if (revEdge.AverageDegree < edge.AverageDegree)
                        {
                            postMatEdges[i] = new Tuple <MatchEdge, EdgeDir>(revEdge,
                                                                             dir == EdgeDir.In ? EdgeDir.Out : EdgeDir.In);
                        }
                    }

                    yield return(new CandidateJoinUnit
                    {
                        TreeRoot = root,
                        PreMatIncomingEdges = new List <MatchEdge>(),
                        PreMatOutgoingEdges = preMatOutEdges.Select(entry => entry.Value).ToList(),
                        PostMatIncomingEdges = postMatEdges.Where(entry => entry.Item2 == EdgeDir.In)
                                               .Select(entry => entry.Item1).ToList(),
                        PostMatOutgoingEdges = postMatEdges.Where(entry => entry.Item2 == EdgeDir.Out)
                                               .Select(entry => entry.Item1).ToList(),
                        UnmaterializedEdges = unpopEdges,
                        JoinHint = JoinHint.Hash,
                    });
                }
            }
        }
Beispiel #25
0
        /// <summary>
        /// Calculate join costs and update components using optimal join method & order
        /// </summary>
        /// <param name="nodeUnitCandidate"></param>
        /// <param name="component"></param>
        /// <param name="nodeTable"></param>
        /// <param name="componentTable"></param>
        /// <param name="joinCondition"></param>
        /// <param name="nodeDegrees"></param>
        /// <param name="estimatedNodeUnitSize"></param>
        /// <param name="estimatedSelectivity"></param>
        /// <returns></returns>
        private static WTableReference GetPlanAndUpdateCost(
            OneHeightTree nodeUnitCandidate,
            MatchComponent component,
            WTableReference nodeTable,
            WTableReference componentTable,
            WBooleanExpression joinCondition,
            double nodeDegrees,
            double joinSelectivity,
            double estimatedNodeUnitSize,
            double estimatedSelectivity)
        {
            var nodeUnitSize      = nodeUnitCandidate.TreeRoot.EstimatedRows * nodeDegrees;
            var componentSize     = component.Size;
            var estimatedCompSize = component.EstimateSize;
            var cost = nodeUnitSize + componentSize;
            //var joinSelectivity =
            //    nodeWithJoinMapping.SelectivityProduct;
            //nodeWithJoinMapping.ExponentialSelevtivityProduct;

            WQualifiedJoin joinTable = new WQualifiedJoin
            {
                FirstTableRef     = componentTable,
                SecondTableRef    = nodeTable,
                JoinCondition     = joinCondition,
                QualifiedJoinType = QualifiedJoinType.Inner,
                JoinHint          = JoinHint.Hash
            };

            var node = nodeUnitCandidate.TreeRoot;

            // If the node is already in the component, then only multiply the degree to get the size
            double nodeUnitActualSize;


            if (component.MaterializedNodeSplitCount[node] > 0)
            {
                nodeUnitActualSize = nodeDegrees;
                var cEstEdge = Math.Pow(1000, component.EdgeMaterilizedDict.Count(e => !e.Value));
                var cSize    = component.EstimateSize / cEstEdge;
                var nSize    = node.EstimatedRows;
                if (nSize > cSize)
                {
                    component.EstimateSize = estimatedNodeUnitSize * cEstEdge * estimatedSelectivity;
                }
                else
                {
                    component.EstimateSize = component.EstimateSize * Math.Pow(1000, nodeUnitCandidate.UnmaterializedEdges.Count) *
                                             estimatedSelectivity;
                }
            }
            else
            {
                nodeUnitActualSize      = nodeUnitSize;
                component.EstimateSize *= estimatedNodeUnitSize * estimatedSelectivity;
            }



            //Update Size
            component.Size *= nodeUnitActualSize * joinSelectivity;

            // Update Cost
            component.Cost += cost;

            // Debug
#if DEBUG
            //Trace.Write(component.NodeUnits.Count+" ");
            //foreach (var n in component.NodeUnits.Where(e => e.Key != node.Node.ExposedName))
            //{
            //    Trace.Write(n.Value.NodeRefName);
            //}
            //Trace.Write(component.NodeUnits[node.Node.ExposedName].NodeRefName+" ");
            //Trace.Write(" "+(long)component.Cost+"   "+(long)component.Size);
            //Trace.Write("   ");
            //foreach (var item in component.PopulatedEdgesName)
            //{
            //    Trace.Write(item + " ");
            //}
            //Trace.Write("; ");
            //foreach (var unpopulatedEdge in component.UnpopulatedEdges)
            //{
            //    Trace.Write(unpopulatedEdge.Alias + " ");
            //}
            //Trace.WriteLine("");
#endif



            // Update TableRef
            // Only consider the size in the first join
            if (component.MaterializedNodeSplitCount.Count == 2 && component.MaterializedNodeSplitCount.All(e => e.Value == 0))
            {
                var nodeInComp = component.MaterializedNodeSplitCount.Keys.First(e => e != node);
                if (nodeUnitSize < componentSize)
                {
                    joinTable.FirstTableRef            = nodeTable;
                    joinTable.SecondTableRef           = componentTable;
                    component.TotalMemory              = component.DeltaMemory = nodeUnitSize;
                    component.EstimateTotalMemory      = component.EstimateDeltaMemory = estimatedNodeUnitSize;
                    component.RightestTableRefSize     = nodeInComp.EstimatedRows;
                    component.FatherOfRightestTableRef = new Tuple <WQualifiedJoin, String>(joinTable,
                                                                                            component.GetNodeRefName(nodeInComp));
                    AdjustEstimation(component, nodeTable, joinTable, nodeUnitSize, estimatedNodeUnitSize,
                                     nodeUnitCandidate.TreeRoot.EstimatedRows, new Tuple <WQualifiedJoin, string>(joinTable, component.GetNodeRefName(node)));
                }
                else
                {
                    component.TotalMemory              = component.DeltaMemory = componentSize;
                    component.EstimateTotalMemory      = component.EstimateDeltaMemory = component.EstimateSize;
                    component.RightestTableRefSize     = nodeUnitCandidate.TreeRoot.EstimatedRows;
                    component.FatherOfRightestTableRef = new Tuple <WQualifiedJoin, String>(joinTable, component.GetNodeRefName(node));
                    AdjustEstimation(component, componentTable, joinTable, componentSize, estimatedCompSize,
                                     nodeInComp.EstimatedRows, new Tuple <WQualifiedJoin, string>(joinTable, component.GetNodeRefName(nodeInComp)));
                }
            }
            else
            {
                double sizeFactor             = 5;//1000;
                double maxMemory              = 1e8;
                double loopJoinInnerThreshold = 10000;
                double loopJoinOuterThreshold = 1000000;


                // Left Deep
                if (componentSize * sizeFactor < nodeUnitSize)
                {
                    var curDeltaMemory = componentSize;
                    component.TotalMemory = component.DeltaMemory + curDeltaMemory;
                    component.DeltaMemory = curDeltaMemory;
                    var curDeltaEstimateMemory = component.EstimateSize;
                    component.EstimateTotalMemory = component.EstimateDeltaMemory + curDeltaEstimateMemory;
                    component.EstimateDeltaMemory = curDeltaEstimateMemory;

                    // Adjust estimation in sql server
                    AdjustEstimation(component, componentTable, joinTable, componentSize, estimatedCompSize,
                                     component.RightestTableRefSize, component.FatherOfRightestTableRef);
                    component.FatherOfRightestTableRef = new Tuple <WQualifiedJoin, string>(joinTable, component.GetNodeRefName(node));
                    component.RightestTableRefSize     = nodeUnitCandidate.TreeRoot.EstimatedRows;
                }
                else
                {
                    // Loop Join
                    if (
                        //((nodeUnitSize < loopJoinInnerThreshold /*&& componentSize < loopJoinOuterThreshold*/) || component.DeltaMemory + componentSize > maxMemory / 100) &&
                        ((nodeUnitSize < loopJoinInnerThreshold && componentSize < loopJoinOuterThreshold) ||
                         component.DeltaMemory + componentSize > maxMemory) &&
                        nodeUnitCandidate.MaterializedEdges.Count == 0)
                    {
                        component.TotalMemory         = component.DeltaMemory;
                        component.EstimateTotalMemory = component.EstimateDeltaMemory;
                        joinTable.JoinHint            = JoinHint.Loop;
                        component.EstimateSize        = estimatedCompSize * estimatedNodeUnitSize /
                                                        nodeUnitCandidate.TreeRoot.TableRowCount;
                    }
                    // Right Deep
                    else
                    {
                        joinTable.FirstTableRef  = nodeTable;
                        joinTable.SecondTableRef = componentTable;

                        AdjustEstimation(component, nodeTable, joinTable, nodeUnitSize, estimatedNodeUnitSize,
                                         node.EstimatedRows, new Tuple <WQualifiedJoin, string>(joinTable, component.GetNodeRefName(node)));

                        component.TotalMemory         += nodeUnitSize;
                        component.DeltaMemory          = component.TotalMemory;
                        component.EstimateTotalMemory += estimatedNodeUnitSize;
                        component.EstimateDeltaMemory  = component.EstimateTotalMemory;
                    }
                }
            }

            return(new WParenthesisTableReference
            {
                Table = joinTable
            });
        }
Beispiel #26
0
        /// <summary>
        /// Transit from current component to the new component in the next state given the Node Unit
        /// </summary>
        /// <param name="candidateTree"></param>
        /// <param name="statisticsCalculator"></param>
        /// <param name="metaData"></param>
        /// <param name="srcNodeStatisticsDict"></param>
        /// <returns></returns>
        public MatchComponent GetNextState(
            CandidateJoinUnit candidateTree,
            IMatchJoinStatisticsCalculator statisticsCalculator,
            GraphMetaData metaData,
            Dictionary<Tuple<string, bool>, Statistics> srcNodeStatisticsDict)
        {
            // Deep copy the component
            var newComponent = new MatchComponent(this);

            // Constrcuts join conditions and retrieves join selectivity
            double preJoinSelectivity, postJoinSelectivity, sqlEstimatedJoinSelectivity;

            var joinCondition = newComponent.ConstructJoinCondition(candidateTree, statisticsCalculator, metaData, srcNodeStatisticsDict,
                out preJoinSelectivity, out postJoinSelectivity, out sqlEstimatedJoinSelectivity);

            // Constructs physical join method and join table references
            newComponent.ConstructPhysicalJoinAndUpdateCost(candidateTree, joinCondition,
               preJoinSelectivity, postJoinSelectivity, sqlEstimatedJoinSelectivity, metaData);

            return newComponent;
        }
        /// <summary>
        /// Get a full one height tree with joint edges and unmaterlized edges,
        /// returns a tuple whose first item is the one height tree and the second item
        /// indicates whether the one height tree only joins with the component's materialized
        /// node on its root.
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="component"></param>
        /// <returns></returns>
        private IEnumerable<Tuple<OneHeightTree, bool>> GetNodeUnits(ConnectedComponent graph, MatchComponent component)
        {
            var nodes = graph.Nodes;
            foreach (var node in nodes.Values.Where(e => !graph.IsTailNode[e]))
            {
                var remainingEdges = node.Neighbors.Where(e => !component.EdgeMaterilizedDict.ContainsKey(e)).ToList();

                // If there exists a component's edge pointing to the 1-heright tree's root
                // or a 1-height tree's edge pointing to the component's node, then generates a valid
                // 1-height tree with edges. Otherwise, if a node can be joint to component as a single
                // split node with unmaterialized edges, generates a 1-height tree with a tag set to true.
                if (component.UnmaterializedNodeMapping.ContainsKey(node) ||
                    remainingEdges.Any(e => component.Nodes.Contains(e.SinkNode)))
                {
                    yield return new Tuple<OneHeightTree, bool>(new OneHeightTree
                    {
                        TreeRoot = node,
                        Edges = remainingEdges
                    }, false);
                }
                else if (remainingEdges.Count > 0 && component.MaterializedNodeSplitCount.Count > 1 &&
                         component.MaterializedNodeSplitCount.ContainsKey(node))
                {
                    yield return new Tuple<OneHeightTree, bool>(new OneHeightTree
                    {
                        TreeRoot = node,
                        Edges = remainingEdges
                    }, true);
                }
            }
        }
 /// <summary>
 /// Get a full one height tree with joint edges and unmaterlized edges,
 /// returns a tuple whose first item is the one height tree and the second item
 /// indicates whether the one height tree only joins with the component's materialized
 /// node on its root.
 /// </summary>
 /// <param name="graph"></param>
 /// <param name="component"></param>
 /// <returns></returns>
 private IEnumerable<OneHeightTree> GetNodeUnits(ConnectedComponent graph, MatchComponent component)
 {
     //var nodes = graph.Nodes;
     //foreach (var node in graph.Nodes.Values)
     foreach (var node in graph.Nodes.Values.Where(n => !component.Nodes.Contains(n)))
     {
         var remainingEdges = node.Neighbors.Where(e => !component.EdgeMaterilizedDict.ContainsKey(e)).ToList();
         if (component.UnmaterializedNodeMapping.ContainsKey(node) ||
             remainingEdges.Any(e => component.Nodes.Contains(e.SinkNode)))
         {
             yield return new OneHeightTree
             {
                 TreeRoot = node,
                 Edges = remainingEdges
             };
         }
     }
 }
Beispiel #29
0
        private CandidateJoinUnit GetCandidateUnits(OneHeightTree tree, MatchComponent component)
        {
            var nodeMatEdgesDict = component.NodeToMaterializedEdgesDict;
            var revEdgeDict      = Graph.ReversedEdgeDict;
            var root             = tree.TreeRoot;

            nodeMatEdgesDict[root.NodeAlias] = new List <Tuple <MatchEdge, MaterializedEdgeType> >();

            List <MatchEdge> inEdges;

            component.UnmaterializedNodeMapping.TryGetValue(root, out inEdges);
            var outEdges   = new List <MatchEdge>();
            var unpopEdges = new List <MatchEdge>();

            foreach (var edge in tree.Edges)
            {
                if (component.Nodes.Contains(edge.SinkNode))
                {
                    outEdges.Add(edge);
                }
                else
                {
                    unpopEdges.Add(edge);
                }
            }

            var rawEdges   = new Dictionary <string, Tuple <MatchEdge, EdgeDir> >();
            var extInEdges = new Dictionary <string, MatchEdge>();

            if (inEdges != null)
            {
                rawEdges = inEdges.ToDictionary(edge => edge.EdgeAlias,
                                                edge => new Tuple <MatchEdge, EdgeDir>(edge, EdgeDir.In));
                extInEdges = inEdges.ToDictionary(edge => edge.EdgeAlias);
            }
            foreach (var edge in outEdges)
            {
                var key = edge.EdgeAlias;
                rawEdges.Add(key, new Tuple <MatchEdge, EdgeDir>(edge, EdgeDir.Out));
                extInEdges.Add(key, revEdgeDict[key]);
            }

            if (extInEdges.Any())
            {
                var firstEdge = extInEdges.FirstOrDefault(e => e.Value.IsReversed == false);
                if (firstEdge.Value == null)
                {
                    firstEdge = extInEdges.First();
                }
                var preMatInEdges = new Dictionary <string, MatchEdge>
                {
                    { firstEdge.Key, firstEdge.Value }
                };

                var postMatEdges = rawEdges.Where(entry => !preMatInEdges.ContainsKey(entry.Key))
                                   .Select(entry => entry.Value).ToList();
                var postMatIncomingEdges = postMatEdges.Where(entry => entry.Item2 == EdgeDir.In)
                                           .Select(entry => entry.Item1).ToList();
                var postMatOutgoingEdges = postMatEdges.Where(entry => entry.Item2 == EdgeDir.Out)
                                           .Select(entry => entry.Item1).ToList();

                nodeMatEdgesDict[firstEdge.Value.SourceNode.NodeAlias].Add(
                    new Tuple <MatchEdge, MaterializedEdgeType>(firstEdge.Value, MaterializedEdgeType.TraversalEdge));
                foreach (var t in postMatEdges)
                {
                    var edge = t.Item1;
                    var type = t.Item2 == EdgeDir.In
                        ? MaterializedEdgeType.RemainingEdge
                        : MaterializedEdgeType.ReverseCheckEdge;
                    nodeMatEdgesDict[edge.SourceNode.NodeAlias].Add(new Tuple <MatchEdge, MaterializedEdgeType>(edge, type));
                }

                return(new CandidateJoinUnit
                {
                    TreeRoot = root,
                    PreMatIncomingEdges = preMatInEdges.Select(entry => entry.Value).ToList(),
                    PreMatOutgoingEdges = new List <MatchEdge>(),
                    PostMatIncomingEdges = postMatIncomingEdges,
                    PostMatOutgoingEdges = postMatOutgoingEdges,
                    UnmaterializedEdges = unpopEdges,
                });
            }
            else
            {
                throw new GraphViewException("This graph pattern is not yet supported.");
            }
        }
Beispiel #30
0
        /// <summary>
        /// Calculate the number used for adjusting the SQL Server estimation in the downsize function.
        /// </summary>
        /// <param name="component"></param>
        /// <param name="tablfRef"></param>
        /// <param name="joinTable"></param>
        /// <param name="size"></param>
        /// <param name="estimatedSize"></param>
        /// <param name="shrinkSize"></param>
        /// <param name="joinTableTuple"></param>
        private static void AdjustEstimation(
            MatchComponent component,
            WTableReference tablfRef,
            WQualifiedJoin joinTable,
            double size,
            double estimatedSize,
            double shrinkSize,
            Tuple <WQualifiedJoin, String> joinTableTuple)
        {
            const int sizeFactor     = 10;
            int       estimateFactor = 0;

            if (size > sizeFactor * estimatedSize)
            {
                estimateFactor = (int)Math.Ceiling(size / estimatedSize);
            }
            else if (sizeFactor * size < estimatedSize)
            {
                estimatedSize          /= shrinkSize;
                component.EstimateSize /= shrinkSize;
                component.FatherListofDownSizeTable.Add(joinTableTuple);
                estimateFactor = (int)Math.Ceiling(size / estimatedSize);
            }
            if (estimateFactor > 1)
            {
                WTableReference crossApplyTable = tablfRef;
                int             pow             = (int)(Math.Floor(Math.Log(estimateFactor, 1000)) + 1);
                int             adjustValue     = (int)Math.Pow(estimateFactor, 1.0 / pow);
                while (pow > 0)
                {
                    crossApplyTable = new WUnqualifiedJoin
                    {
                        FirstTableRef  = crossApplyTable,
                        SecondTableRef = new WSchemaObjectFunctionTableReference
                        {
                            SchemaObject = new WSchemaObjectName(
                                new Identifier {
                                Value = "dbo"
                            },
                                new Identifier {
                                Value = "UpSizeFunction"
                            }),
                            Parameters = new List <WScalarExpression>
                            {
                                new WValueExpression {
                                    Value = adjustValue.ToString()
                                }
                            },
                            Alias = new Identifier
                            {
                                Value = Path.GetRandomFileName().Replace(".", "").Substring(0, 8),
                            }
                        },
                        UnqualifiedJoinType = UnqualifiedJoinType.CrossApply
                    };
                    pow--;
                    component.EstimateSize *= adjustValue;
                }
                joinTable.FirstTableRef = crossApplyTable;
            }
        }
Beispiel #31
0
        private void UpdateComponent(MatchComponent curComponent, CandidateJoinUnit candidateTree)
        {
            Dictionary <string, MatchNode>            nodes = curComponent.Nodes;
            Dictionary <MatchEdge, bool>              edgeMaterializedDict      = curComponent.EdgeMaterilizedDict;
            Dictionary <MatchNode, List <MatchEdge> > unmaterializedNodeMapping = curComponent.UnmaterializedNodeMapping;
            MatchNode root = candidateTree.TreeRoot;

            if (!nodes.ContainsKey(root.NodeAlias))
            {
                nodes.Add(root.NodeAlias, new MatchNode(root));
            }
            curComponent.MaterializedNodeSplitCount[root] = 0;

            List <Tuple <MaterializedOrder, MatchEdge> > inEdges =
                candidateTree.PreMatIncomingEdges.Select(
                    e => new Tuple <MaterializedOrder, MatchEdge>(MaterializedOrder.Pre, e))
                .Union(
                    candidateTree.PostMatIncomingEdges.Select(
                        e => new Tuple <MaterializedOrder, MatchEdge>(MaterializedOrder.Post, e)))
                .ToList();

            List <Tuple <MaterializedOrder, MatchEdge> > outEdges =
                candidateTree.PreMatOutgoingEdges.Select(
                    e => new Tuple <MaterializedOrder, MatchEdge>(MaterializedOrder.Pre, e))
                .Union(
                    candidateTree.PostMatOutgoingEdges.Select(
                        e => new Tuple <MaterializedOrder, MatchEdge>(MaterializedOrder.Post, e)))
                .ToList();

            if (inEdges.Any())
            {
                unmaterializedNodeMapping.Remove(root);

                foreach (Tuple <MaterializedOrder, MatchEdge> t in inEdges)
                {
                    MaterializedOrder order = t.Item1;
                    MatchEdge         edge  = t.Item2;

                    edgeMaterializedDict[edge] = true;
                    List <string> adjListProperties = this.PopulateAdjacencyListProperties(edge);
                    MatchNode     node = curComponent.Nodes[edge.SourceNode.NodeAlias];
                    foreach (string adjListProperty in adjListProperties)
                    {
                        node.Properties.Add(adjListProperty);
                    }
                }
            }

            if (outEdges.Any())
            {
                foreach (Tuple <MaterializedOrder, MatchEdge> t in outEdges)
                {
                    MaterializedOrder order = t.Item1;
                    MatchEdge         edge  = t.Item2;

                    edgeMaterializedDict[edge] = true;
                    List <string> adjListProperties = this.PopulateAdjacencyListProperties(edge);
                    MatchNode     node = curComponent.Nodes[edge.SourceNode.NodeAlias];
                    foreach (string adjListProperty in adjListProperties)
                    {
                        node.Properties.Add(adjListProperty);
                    }
                }
            }

            List <MatchEdge> unmatEdges = candidateTree.UnmaterializedEdges;

            foreach (MatchEdge unmatEdge in unmatEdges)
            {
                edgeMaterializedDict[unmatEdge] = false;;
                List <MatchEdge> unmatNodeInEdges = unmaterializedNodeMapping.GetOrCreate(unmatEdge.SinkNode);
                unmatNodeInEdges.Add(unmatEdge);
            }
        }
Beispiel #32
0
        /// <summary>
        /// Transit from current component to the new component in the next state given the Node Unit
        /// </summary>
        /// <param name="candidateTree"></param>
        /// <param name="densityDict"></param>
        /// <param name="subGraph"></param>
        /// <param name="statisticsCalculator"></param>
        /// <returns></returns>
        public MatchComponent GetNextState(
            OneHeightTree candidateTree,
            Dictionary <string, double> densityDict,
            IMatchJoinStatisticsCalculator statisticsCalculator)
        {
            var newComponent = new MatchComponent(this);
            var root         = candidateTree.TreeRoot;

            WBooleanExpression joinCondition = null;
            string             nodeName      = "";


            // Update Nodes
            if (newComponent.MaterializedNodeSplitCount.ContainsKey(root))
            {
                newComponent.MaterializedNodeSplitCount[root]++;
                nodeName      = newComponent.GetNodeRefName(root);
                joinCondition = new WBooleanComparisonExpression
                {
                    FirstExpr = new WColumnReferenceExpression
                    {
                        ColumnType          = ColumnType.Regular,
                        MultiPartIdentifier = new WMultiPartIdentifier(
                            new Identifier {
                            Value = root.RefAlias
                        },
                            new Identifier {
                            Value = "GlobalNodeId"
                        }
                            ),
                    },
                    SecondExpr = new WColumnReferenceExpression
                    {
                        ColumnType          = ColumnType.Regular,
                        MultiPartIdentifier = new WMultiPartIdentifier(
                            new Identifier {
                            Value = nodeName
                        },
                            new Identifier {
                            Value = "GlobalNodeId"
                        }
                            ),
                    },
                    ComparisonType = BooleanComparisonType.Equals
                };
            }
            else
            {
                nodeName = root.RefAlias;
                newComponent.Nodes.Add(root);
                newComponent.MaterializedNodeSplitCount[root] = 0;
                newComponent.StatisticsDict[root]             = new ColumnStatistics {
                    Selectivity = 1.0 / root.TableRowCount
                };
            }

            // Constructs table reference
            WTableReference nodeTable = new WNamedTableReference
            {
                Alias = new Identifier {
                    Value = nodeName
                },
                TableObjectName = root.TableObjectName
            };
            WTableReference compTable = newComponent.TableRef;

            // Updates join conditions
            double selectivity  = 1.0;
            double degrees      = 1.0;
            var    DensityCount = new Dictionary <string, int>(StringComparer.CurrentCultureIgnoreCase);

            List <MatchEdge> inEdges;

            if (newComponent.UnmaterializedNodeMapping.TryGetValue(root, out inEdges))
            {
                var  firstEdge    = inEdges.First();
                bool materialized = newComponent.EdgeMaterilizedDict[firstEdge];
                newComponent.UnmaterializedNodeMapping.Remove(root);
                selectivity *= 1.0 / root.TableRowCount;

                // Component materialized edge to root
                if (materialized)
                {
                    joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition, new WBooleanComparisonExpression
                    {
                        FirstExpr = new WColumnReferenceExpression
                        {
                            ColumnType          = ColumnType.Regular,
                            MultiPartIdentifier = new WMultiPartIdentifier(
                                new Identifier {
                                Value = firstEdge.EdgeAlias
                            },
                                new Identifier {
                                Value = "Sink"
                            }
                                ),
                        },
                        SecondExpr = new WColumnReferenceExpression
                        {
                            ColumnType          = ColumnType.Regular,
                            MultiPartIdentifier = new WMultiPartIdentifier(
                                new Identifier {
                                Value = nodeName
                            },
                                new Identifier {
                                Value = "GlobalNodeId"
                            }
                                )
                        },
                        ComparisonType = BooleanComparisonType.Equals
                    });

                    //var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[root],
                    //    new ColumnStatistics {Selectivity = 1.0/root.TableRowCount});
                    //selectivity *= statistics.Selectivity;
                    //newComponent.StatisticsDict[root] = statistics;

                    if (DensityCount.ContainsKey(root.TableObjectName.ToString()))
                    {
                        DensityCount[root.TableObjectName.ToString()]++;
                    }
                    else
                    {
                        DensityCount[root.TableObjectName.ToString()] = 1;
                    }
                }
                // Component unmaterialized edge to root
                else
                {
                    ColumnStatistics statistics = null;
                    foreach (var edge in inEdges)
                    {
                        // Update component table
                        compTable = SpanTableRef(compTable, edge, newComponent.GetNodeRefName(edge.SourceNode));

                        newComponent.EdgeMaterilizedDict[edge] = true;
                        joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition,
                                                                             new WBooleanComparisonExpression
                        {
                            FirstExpr = new WColumnReferenceExpression
                            {
                                ColumnType          = ColumnType.Regular,
                                MultiPartIdentifier = new WMultiPartIdentifier(
                                    new Identifier {
                                    Value = edge.EdgeAlias
                                },
                                    new Identifier {
                                    Value = "Sink"
                                }
                                    ),
                            },
                            SecondExpr = new WColumnReferenceExpression
                            {
                                ColumnType          = ColumnType.Regular,
                                MultiPartIdentifier = new WMultiPartIdentifier(
                                    new Identifier {
                                    Value = nodeName
                                },
                                    new Identifier {
                                    Value = "GlobalNodeId"
                                }
                                    )
                            },
                            ComparisonType = BooleanComparisonType.Equals
                        });
                        statistics = ColumnStatistics.UpdateHistogram(statistics,
                                                                      newComponent.Context.GetEdgeStatistics(edge));
                        selectivity *= statistics.Selectivity;
                    }
                    newComponent.StatisticsDict[root] = statistics;

                    if (DensityCount.ContainsKey(root.TableObjectName.ToString()))
                    {
                        DensityCount[root.TableObjectName.ToString()] += inEdges.Count;
                    }
                    else
                    {
                        DensityCount[root.TableObjectName.ToString()] = inEdges.Count;
                    }
                }
            }

            var jointEdges      = candidateTree.MaterializedEdges;
            int sinkToSinkCount = 0;

            foreach (var jointEdge in jointEdges)
            {
                // Update node table
                nodeTable = SpanTableRef(nodeTable, jointEdge, nodeName);
                degrees  *= jointEdge.AverageDegree;

                newComponent.EdgeMaterilizedDict[jointEdge] = true;
                var sinkNode = jointEdge.SinkNode;
                // Leaf to component materialized node
                if (newComponent.MaterializedNodeSplitCount.ContainsKey(sinkNode))
                {
                    joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition,
                                                                         new WBooleanComparisonExpression
                    {
                        FirstExpr = new WColumnReferenceExpression
                        {
                            ColumnType          = ColumnType.Regular,
                            MultiPartIdentifier = new WMultiPartIdentifier(
                                new Identifier {
                                Value = jointEdge.EdgeAlias
                            },
                                new Identifier {
                                Value = "Sink"
                            }
                                ),
                        },
                        SecondExpr = new WColumnReferenceExpression
                        {
                            ColumnType          = ColumnType.Regular,
                            MultiPartIdentifier = new WMultiPartIdentifier(
                                new Identifier {
                                Value = sinkNode.RefAlias
                            },
                                new Identifier {
                                Value = "GlobalNodeId"
                            }
                                )
                        },
                        ComparisonType = BooleanComparisonType.Equals
                    });
                    var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[sinkNode],
                                                                      newComponent.Context.GetEdgeStatistics(jointEdge));
                    selectivity *= statistics.Selectivity;
                    newComponent.StatisticsDict[sinkNode] = statistics;

                    if (DensityCount.ContainsKey(sinkNode.TableObjectName.ToString()))
                    {
                        DensityCount[sinkNode.TableObjectName.ToString()]++;
                    }
                    else
                    {
                        DensityCount[sinkNode.TableObjectName.ToString()] = 1;
                    }
                }
                // Leaf to component unmaterialized node
                else
                {
                    inEdges = newComponent.UnmaterializedNodeMapping[sinkNode];
                    var  firstEdge      = inEdges.First();
                    bool materlizedEdge = newComponent.EdgeMaterilizedDict[firstEdge];

                    // Leaf to materialized leaf
                    if (materlizedEdge)
                    {
                        joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition,
                                                                             new WBooleanComparisonExpression
                        {
                            FirstExpr = new WColumnReferenceExpression
                            {
                                ColumnType          = ColumnType.Regular,
                                MultiPartIdentifier = new WMultiPartIdentifier(
                                    new Identifier {
                                    Value = jointEdge.EdgeAlias
                                },
                                    new Identifier {
                                    Value = "Sink"
                                }
                                    ),
                            },
                            SecondExpr = new WColumnReferenceExpression
                            {
                                ColumnType          = ColumnType.Regular,
                                MultiPartIdentifier = new WMultiPartIdentifier(
                                    new Identifier {
                                    Value = firstEdge.EdgeAlias
                                },
                                    new Identifier {
                                    Value = "Sink"
                                }
                                    )
                            },
                            ComparisonType = BooleanComparisonType.Equals
                        });

                        sinkToSinkCount++;
                        var statistics = ColumnStatistics.UpdateHistogram(newComponent.StatisticsDict[sinkNode],
                                                                          newComponent.Context.GetEdgeStatistics(jointEdge));
                        selectivity *= statistics.Selectivity;
                        newComponent.StatisticsDict[sinkNode] = statistics;
                    }
                    // Leaf to unmaterialized leaf
                    else
                    {
                        ColumnStatistics compSinkNodeStatistics = null;
                        foreach (var inEdge in inEdges)
                        {
                            compTable = SpanTableRef(compTable, inEdge, newComponent.GetNodeRefName(inEdge.SourceNode));
                            newComponent.EdgeMaterilizedDict[inEdge] = true;
                            joinCondition = WBooleanBinaryExpression.Conjunction(joinCondition,
                                                                                 new WBooleanComparisonExpression
                            {
                                FirstExpr = new WColumnReferenceExpression
                                {
                                    ColumnType          = ColumnType.Regular,
                                    MultiPartIdentifier = new WMultiPartIdentifier(
                                        new Identifier {
                                        Value = jointEdge.EdgeAlias
                                    },
                                        new Identifier {
                                        Value = "Sink"
                                    }
                                        ),
                                },
                                SecondExpr = new WColumnReferenceExpression
                                {
                                    ColumnType          = ColumnType.Regular,
                                    MultiPartIdentifier = new WMultiPartIdentifier(
                                        new Identifier {
                                        Value = inEdge.EdgeAlias
                                    },
                                        new Identifier {
                                        Value = "Sink"
                                    }
                                        )
                                },
                                ComparisonType = BooleanComparisonType.Equals
                            });

                            sinkToSinkCount++;
                            var leafToLeafStatistics = statisticsCalculator.GetLeafToLeafStatistics(jointEdge, inEdge);
                            selectivity           *= leafToLeafStatistics.Selectivity;
                            compSinkNodeStatistics =
                                ColumnStatistics.UpdateHistogram(compSinkNodeStatistics,
                                                                 newComponent.Context.GetEdgeStatistics(inEdge));
                        }
                        newComponent.StatisticsDict[sinkNode] = compSinkNodeStatistics;
                    }
                }
            }

            var unmatEdges = candidateTree.UnmaterializedEdges;

            foreach (var unmatEdge in unmatEdges)
            {
                newComponent.EdgeMaterilizedDict[unmatEdge] = false;
                newComponent.Nodes.Add(unmatEdge.SinkNode);
                var sinkNodeInEdges = newComponent.UnmaterializedNodeMapping.GetOrCreate(unmatEdge.SinkNode);
                sinkNodeInEdges.Add(unmatEdge);
                degrees *= unmatEdge.AverageDegree;
            }

            // Calculate Estimated Join Selectivity & Estimated Node Size
            double estimatedSelectity = 1.0;
            int    count    = 0;
            bool   sinkJoin = false;

            foreach (var item in densityDict.Where(e => DensityCount.ContainsKey(e.Key)))
            {
                var density            = item.Value;
                var curJoinCount       = DensityCount[item.Key];
                var curJoinSelectitivy = Math.Pow(density, 2 - Math.Pow(2, 1 - curJoinCount));
                if (!sinkJoin && ColumnStatistics.DefaultDensity < density)
                {
                    var curSinkJoinSelectivity = Math.Pow(ColumnStatistics.DefaultDensity,
                                                          2 - Math.Pow(2, 1 - sinkToSinkCount));
                    estimatedSelectity *= Math.Pow(curSinkJoinSelectivity, Math.Pow(2, -count));
                    count   += sinkToSinkCount;
                    sinkJoin = true;
                }
                estimatedSelectity *= Math.Pow(curJoinSelectitivy, Math.Pow(2, -count));
                count += curJoinCount;
            }

            var estimatedNodeUnitSize = root.EstimatedRows *
                                        Math.Pow(1000, candidateTree.MaterializedEdges.Count + candidateTree.UnmaterializedEdges.Count);


            // Update Table Reference
            newComponent.TableRef = GetPlanAndUpdateCost(candidateTree, newComponent, nodeTable, compTable, joinCondition,
                                                         degrees, selectivity, estimatedNodeUnitSize, estimatedSelectity);

            return(newComponent);
        }
Beispiel #33
0
        public IEnumerable <CandidateJoinUnit> GetCandidateUnits(IEnumerable <Tuple <OneHeightTree, bool> > treeTuples, MatchComponent component)
        {
            foreach (var treeTuple in treeTuples)
            {
                var  tree       = treeTuple.Item1;
                bool singleNode = treeTuple.Item2;
                var  root       = tree.TreeRoot;

                List <MatchEdge> jointEdges = new List <MatchEdge>();
                List <MatchEdge> unpopEdges = new List <MatchEdge>();

                if (singleNode)
                {
                    unpopEdges = tree.Edges;
                }
                else
                {
                    foreach (var edge in tree.Edges)
                    {
                        if (component.Nodes.Contains(edge.SinkNode))
                        {
                            jointEdges.Add(edge);
                        }
                        else
                        {
                            unpopEdges.Add(edge);
                        }
                    }
                }
                //var jointEdges = tree.MaterializedEdges;
                //var unpopEdges = tree.UnmaterializedEdges;
                int joinEdgesCount  = jointEdges.Count;
                int unpopEdgesCount = unpopEdges.Count;

                int num = (int)Math.Pow(2, joinEdgesCount) - 1;
                while (num >= 0)
                {
                    if (joinEdgesCount > 0 && num == 0)
                    {
                        break;
                    }
                    var newJointEdges = new List <MatchEdge>();
                    for (int i = 0; i < joinEdgesCount; i++)
                    {
                        int index = (1 << i);
                        if ((num & index) != 0)
                        {
                            var edge = jointEdges[i];
                            newJointEdges.Add(edge);
                        }
                    }

                    int eNum = (int)Math.Pow(2, unpopEdgesCount) - 1;
                    while (eNum >= 0)
                    {
                        if (eNum == 0 && singleNode)
                        {
                            break;
                        }
                        var newUnpopEdges = new List <MatchEdge>();
                        for (int i = 0; i < unpopEdgesCount; i++)
                        {
                            int index = (1 << i);
                            if ((eNum & index) != 0)
                            {
                                newUnpopEdges.Add(unpopEdges[i]);
                            }
                        }

                        yield return(new CandidateJoinUnit
                        {
                            TreeRoot = root,
                            MaterializedEdges = newJointEdges,
                            UnmaterializedEdges = newUnpopEdges,
                        });

                        eNum--;
                    }
                    num--;
                }
            }
        }