hbtoo commented on a change in pull request #2187:
URL: https://github.com/apache/calcite/pull/2187#discussion_r502834591



##########
File path: 
core/src/main/java/org/apache/calcite/plan/volcano/VolcanoPlanner.java
##########
@@ -906,6 +903,60 @@ void rename(RelNode rel) {
     }
   }
 
+  /**
+   * Checks whether a relexp has made any subset cheaper, and if it so,
+   * propagate new cost to parent rel nodes.
+   *
+   * @param rel       Relational expression whose cost has improved
+   */
+  void propagateCostImprovements(RelNode rel) {
+    RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
+    Map<RelNode, RelOptCost> propagateRels = new HashMap<>();
+    PriorityQueue<RelNode> propagateHeap = new PriorityQueue<>((o1, o2) -> {
+      RelOptCost c1 = propagateRels.get(o1);
+      RelOptCost c2 = propagateRels.get(o2);
+      if (c1.equals(c2)) {
+        return 0;
+      } else if (c1.isLt(c2)) {
+        return -1;
+      }
+      return 1;
+    });
+    propagateRels.put(rel, getCost(rel, mq));
+    propagateHeap.offer(rel);
+
+    while (!propagateHeap.isEmpty()) {
+      RelNode relNode = propagateHeap.poll();
+      RelOptCost cost = propagateRels.get(relNode);
+
+      for (RelSubset subset : getSet(relNode).subsets) {
+        if (relNode.getTraitSet().satisfies(subset.getTraitSet())) {
+          // Update subset best cost when we find a cheaper rel or the current
+          // best's cost is changed
+          if (cost.isLt(subset.bestCost)) {
+            subset.timestamp++;
+            LOGGER.trace("Subset cost changed: subset [{}] cost was {} now {}",
+                subset, subset.bestCost, cost);
+
+            subset.bestCost = cost;
+            subset.best = relNode;
+            // since best was changed, cached metadata for this subset should 
be removed
+            mq.clearCache(subset);
+
+            subset.getParents().forEach(parent -> {
+              mq.clearCache(parent);
+              if (propagateRels.put(parent, getCost(parent, mq)) != null) {
+                // Cost changed, force the heap to adjust its ordering
+                propagateHeap.remove(parent);

Review comment:
       True. However note that when this code is hit, it means that we've found 
a second update path to this same relNode. This is exactly the case where this 
patch improves performance. Before this patch, it means that this relNode (and 
thus everything above it) will be updated twice. With this patch, we only need 
to repopulate the heap with this relNode with updated cost. Although it is 
indeed O(N), it is already much faster than before. 
   
   Also note that technically, the heap implementation can be improved to 
reduce this from O(N) to O(logN). However it might not be essential here. 




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to