You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ba...@apache.org on 2006/04/12 22:51:14 UTC

svn commit: r393608 - /db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OptimizerImpl.java

Author: bandaram
Date: Wed Apr 12 13:51:09 2006
New Revision: 393608

URL: http://svn.apache.org/viewcvs?rev=393608&view=rev
Log:
DERBY-1073: Address subquery timeout mechanism issue when parent query has not timed out, but the subquery has. Find a complete and valid plan for the subquery and return this cost.

Submitted by Army Brown (qozinx@gmail.com)

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OptimizerImpl.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OptimizerImpl.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OptimizerImpl.java?rev=393608&r1=393607&r2=393608&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OptimizerImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/OptimizerImpl.java Wed Apr 12 13:51:09 2006
@@ -377,6 +377,60 @@
 			}
 		}
 
+		if (timeExceeded && bestCost.isUninitialized())
+		{
+			/* We can get here if this OptimizerImpl is for a subquery
+			 * that timed out for a previous permutation of the outer
+			 * query, but then the outer query itself did _not_ timeout.
+			 * In that case we'll end up back here for another round of
+			 * optimization, but our timeExceeded flag will be true.
+			 * We don't want to reset all of the timeout state here
+			 * because that could lead to redundant work (see comments
+			 * in prepForNextRound()), but we also don't want to return
+			 * without having a plan, because then we'd return an unfairly
+			 * high "bestCost" value--i.e. Double.MAX_VALUE.  Note that
+			 * we can't just revert back to whatever bestCost we had
+			 * prior to this because that cost is for some previous
+			 * permutation of the outer query--not the current permutation--
+			 * and thus would be incorrect.  So instead we have to delay
+			 * the timeout until we find a complete (and valid) join order,
+			 * so that we can return a valid cost estimate.  Once we have
+			 * a valid cost we'll then go through the timeout logic
+			 * and stop optimizing.
+			 * 
+			 * All of that said, instead of just trying the first possible
+			 * join order, we jump to the join order that gave us the best
+			 * cost in previous rounds.  We know that such a join order exists
+			 * because that's how our timeout value was set to begin with--so
+			 * if there was no best join order, we never would have timed out
+			 * and thus we wouldn't be here.
+			 */
+			if (permuteState != JUMPING)
+			{
+				// By setting firstLookOrder to our target join order
+				// and then setting our permuteState to JUMPING, we'll
+				// jump to the target join order and get the cost.  That
+				// cost will then be saved as bestCost, allowing us to
+				// proceed with normal timeout logic.
+				for (int i = 0; i < numOptimizables; i++)
+					firstLookOrder[i] = bestJoinOrder[i];
+				permuteState = JUMPING;
+
+				// If we were in the middle of a join order when this
+				// happened, then reset the join order before jumping.
+				if (joinPosition > 0)
+					rewindJoinOrder();
+			}
+
+			// Reset the timeExceeded flag so that we'll keep going
+			// until we find a complete join order.  NOTE: we intentionally
+			// do _not_ reset the timeOptimizationStarted value because we
+			// we want to go through this timeout logic for every
+			// permutation, to make sure we timeout as soon as we have
+			// our first complete join order.
+			timeExceeded = false;
+		}
+
 		/*
 		** Pick the next table in the join order, if there is an unused position
 		** in the join order, and the current plan is less expensive than