db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From krist...@apache.org
Subject svn commit: r1069160 - in /db/derby/code/trunk/java/engine/org/apache/derby: catalog/ catalog/types/ iapi/sql/dictionary/ iapi/store/access/ impl/sql/ impl/sql/compile/
Date Wed, 09 Feb 2011 22:52:30 GMT
Author: kristwaa
Date: Wed Feb  9 22:52:30 2011
New Revision: 1069160

URL: http://svn.apache.org/viewvc?rev=1069160&view=rev
Log:
DERBY-4938: Implement istat scheduling/triggering 

Added logic to automatically schedule creation and updates of index cardinality
statistics when compiling prepared statements.
See the parent issue and linked issues for more details.

Patch file: derby-4938-1a-istat_scheduling.diff


Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/catalog/Statistics.java
    db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/StatisticsImpl.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/RowCountable.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/Statistics.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/Statistics.java?rev=1069160&r1=1069159&r2=1069160&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/Statistics.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/Statistics.java Wed Feb  9 22:52:30
2011
@@ -33,6 +33,13 @@ package org.apache.derby.catalog;
 
 public interface Statistics
 {
+    /**
+     * Returns the estimated number of rows in the index.
+     *
+     * @return Number of rows.
+     */
+    long getRowEstimate();
+
 	/**
 	 * @return the selectivity for a set of predicates.
 	 */

Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/StatisticsImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/StatisticsImpl.java?rev=1069160&r1=1069159&r2=1069160&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/StatisticsImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/StatisticsImpl.java Wed
Feb  9 22:52:30 2011
@@ -25,7 +25,6 @@ import org.apache.derby.catalog.Statisti
 import org.apache.derby.iapi.services.io.Formatable;
 import org.apache.derby.iapi.services.io.StoredFormatIds;
 import org.apache.derby.iapi.services.io.FormatableHashtable;
-import org.apache.derby.iapi.services.io.FormatableLongHolder;
 
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
@@ -63,6 +62,11 @@ public class StatisticsImpl	implements S
 	public StatisticsImpl()
 	{}
 
+    /** {@inheritDoc} */
+    public long getRowEstimate() {
+        return numRows;
+    }
+
 	/** @see Statistics#selectivity */
 	public double selectivity(Object[] predicates)
 	{

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java?rev=1069160&r1=1069159&r2=1069160&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/dictionary/TableDescriptor.java
Wed Feb  9 22:52:30 2011
@@ -24,17 +24,18 @@ package org.apache.derby.iapi.sql.dictio
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 
 import org.apache.derby.catalog.Dependable;
 import org.apache.derby.catalog.DependableFinder;
 import org.apache.derby.catalog.UUID;
 import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.reference.Property;
 import org.apache.derby.iapi.reference.SQLState;
 import org.apache.derby.iapi.services.io.FormatableBitSet;
 import org.apache.derby.iapi.services.io.StoredFormatIds;
 import org.apache.derby.iapi.services.sanity.SanityManager;
 import org.apache.derby.iapi.services.context.ContextService;
+import org.apache.derby.iapi.services.property.PropertyUtil;
 import org.apache.derby.iapi.sql.StatementType;
 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
 import org.apache.derby.iapi.sql.depend.DependencyManager;
@@ -102,6 +103,32 @@ public class TableDescriptor extends Tup
 	public static final char	TABLE_LOCK_GRANULARITY = 'T';
 	public static final char	DEFAULT_LOCK_GRANULARITY = ROW_LOCK_GRANULARITY;
 
+    // Constants for the automatic index statistics update feature.
+    public static final int ISTATS_CREATE_THRESHOLD;
+    public static final int ISTATS_ABSDIFF_THRESHOLD;
+    public static final double ISTATS_LNDIFF_THRESHOLD;
+    static {
+        ISTATS_CREATE_THRESHOLD = PropertyUtil.getSystemInt(
+                Property.STORAGE_AUTO_INDEX_STATS_DEBUG_CREATE_THRESHOLD,
+                Property.STORAGE_AUTO_INDEX_STATS_DEBUG_CREATE_THRESHOLD_DEFAULT
+                );
+        ISTATS_ABSDIFF_THRESHOLD = PropertyUtil.getSystemInt(
+            Property.STORAGE_AUTO_INDEX_STATS_DEBUG_ABSDIFF_THRESHOLD,
+            Property.STORAGE_AUTO_INDEX_STATS_DEBUG_ABSDIFF_THRESHOLD_DEFAULT);
+        double tmpLog2Diff =
+            Property.STORAGE_AUTO_INDEX_STATS_DEBUG_LNDIFF_THRESHOLD_DEFAULT;
+        try {
+            String tmpStr = PropertyUtil.getSystemProperty(
+                    Property.STORAGE_AUTO_INDEX_STATS_DEBUG_LNDIFF_THRESHOLD);
+            if (tmpStr != null) {
+                tmpLog2Diff = Double.parseDouble(tmpStr);
+            }
+        } catch (NumberFormatException nfe) {
+            // Ignore, use the default.
+        }
+        ISTATS_LNDIFF_THRESHOLD = tmpLog2Diff;
+    }
+
 	/**
 	*/
 
@@ -109,6 +136,8 @@ public class TableDescriptor extends Tup
 	private char					lockGranularity;
 	private boolean					onCommitDeleteRows; //true means on commit delete rows, false means
on commit preserve rows of temporary table.
 	private boolean					onRollbackDeleteRows; //true means on rollback delete rows. This is
the only value supported.
+    private boolean                 indexStatsUpToDate = true;
+    private String                  indexStatsUpdateReason;
 	SchemaDescriptor				schema;
 	String							tableName;
 	UUID							oid;
@@ -1265,6 +1294,74 @@ public class TableDescriptor extends Tup
 		return statisticsDescriptorList = dd.getStatisticsDescriptors(this);
 	}
 
+    /**
+     * Marks the cardinality statistics for the indexes associated with this
+     * table for update if they are considered stale, or for creation if they
+     * don't exist, and if it is considered useful to update/create them.
+     *
+     * @param tableRowCountEstimate row count estimate for this table
+     * @throws StandardException if obtaining index statistics fails
+     */
+    public void markForIndexStatsUpdate(long tableRowCountEstimate)
+            throws StandardException {
+        List sdl = getStatistics();
+        if (sdl.isEmpty() && tableRowCountEstimate >= ISTATS_CREATE_THRESHOLD)
{
+            // No statistics exists, create them.
+            indexStatsUpToDate = false;
+            indexStatsUpdateReason = "no stats, row-estimate=" +
+                    tableRowCountEstimate;
+            return;
+        }
+
+        // Check the state of the existing indexes (if any).
+        Iterator statIter = sdl.iterator();
+        while (statIter.hasNext()) {
+            StatisticsDescriptor sd = (StatisticsDescriptor)statIter.next();
+            long indexRowCountEstimate = sd.getStatistic().getRowEstimate();
+            long diff = Math.abs(tableRowCountEstimate - indexRowCountEstimate);
+            // TODO: Set a proper limit here to avoid too frequent updates.
+            if (diff >= ISTATS_ABSDIFF_THRESHOLD) {
+                double cmp = Math.abs(
+                        Math.log(indexRowCountEstimate) -
+                        Math.log(tableRowCountEstimate));
+                if (Double.compare(cmp, ISTATS_LNDIFF_THRESHOLD) == 1) {
+                    indexStatsUpToDate= false;
+                    indexStatsUpdateReason = "t-est=" + tableRowCountEstimate +
+                            ", i-est=" + indexRowCountEstimate + " => cmp=" +
+                            cmp;
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Tells if the index statistics for the indexes associated with this table
+     * are consideres up-to-date, and clears the state.
+     *
+     * @return {@code true} if the statistics are considered up-to-date,
+     *      {@code false} if not.
+     */
+    public boolean getAndClearIndexStatsIsUpToDate() {
+        // TODO: Consider adding a flag telling if statistics update has been
+        //       scheduled already.
+        boolean tmp = indexStatsUpToDate;
+        indexStatsUpToDate = true;
+        return tmp;
+    }
+
+    /**
+     * Returns the update criteria telling why the statistics are considered
+     * stale.
+     * <p>
+     * This method is used for debugging.
+     *
+     * @return A string describing the update criteria that were met.
+     */
+    public String getIndexStatsUpdateReason() {
+        return indexStatsUpdateReason;
+    }
+
 	/** 
 	 * Are there statistics for this particular conglomerate.
 	 *

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/RowCountable.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/RowCountable.java?rev=1069160&r1=1069159&r2=1069160&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/RowCountable.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/store/access/RowCountable.java Wed
Feb  9 22:52:30 2011
@@ -24,15 +24,11 @@ package org.apache.derby.iapi.store.acce
 import org.apache.derby.iapi.error.StandardException; 
 
 /**
-
-RowCountable provides the interfaces to read and write row counts in
-tables.
-<p>
-@see ScanController
-@see StoreCostController
-
-**/
-
+ * Allows clients to read and write row count estimates for conglomerates.
+ *
+ * @see ScanController
+ * @see StoreCostController
+ */
 public interface RowCountable
 {
     /**
@@ -52,23 +48,28 @@ public interface RowCountable
      * of rows in the heap table to estimate the number of rows in the index
      * rather than use the index estimated row count.
      *
-	 * @return The total estimated number of rows in the conglomerate.
+     * @return The total estimated number of rows in the conglomerate.
      *
-	 * @exception  StandardException  Standard exception policy.
-     **/
+     * @throws  StandardException  Standard exception policy.
+     */
     public long getEstimatedRowCount()
-		throws StandardException;
+        throws StandardException;
 
     /**
      * Set the total estimated number of rows in the container.
      * <p>
      * Often, after a scan, the client of RawStore has a much better estimate
-     * of the number of rows in the container than what store has.  For 
-     * instance if we implement some sort of update statistics command, or
-     * just after a create index a complete scan will have been done of the
-     * table.  In this case this interface allows the client to set the
-     * estimated row count for the container, and store will use that number
-     * for all future references.
+     * of the number of rows in the container than what store has. Currently,
+     * a scan, followed by an update of the estimate, will be performed when:
+     * <ul>
+     *      <li>running SYSCS_UTIL.SYSCS_UPDATE_STATISTICS</li>
+     *      <li>the automatic update of index statistics kicks in
+     *          (see {@code IndexStatisticsDaemon})</li>
+     *      <li>performing table scans</li>
+     *      <li>creating an index on a populated table</li>
+     * </ul>
+     * This interface allows the client to set the estimated row count for the
+     * container, and store will use that number for all future references.
      * <p>
      * This routine can also be used to set the estimated row count in the
      * index to the number of rows in the base table, another workaround for
@@ -76,9 +77,9 @@ public interface RowCountable
      *
      * @param count the estimated number of rows in the container.
      *
-	 * @exception  StandardException  Standard exception policy.
-     **/
+     * @throws  StandardException  Standard exception policy.
+     */
     public void setEstimatedRowCount(long count)
-		throws StandardException;
+        throws StandardException;
 
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java?rev=1069160&r1=1069159&r2=1069160&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericStatement.java Wed Feb
 9 22:52:30 2011
@@ -25,6 +25,7 @@ import java.sql.Timestamp;
 
 import org.apache.derby.iapi.error.StandardException;
 import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.services.daemon.IndexStatisticsDaemon;
 import org.apache.derby.iapi.services.loader.GeneratedClass;
 import org.apache.derby.iapi.services.monitor.Monitor;
 import org.apache.derby.iapi.services.sanity.SanityManager;
@@ -39,6 +40,7 @@ import org.apache.derby.iapi.sql.conn.La
 import org.apache.derby.iapi.sql.conn.StatementContext;
 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
 import org.apache.derby.iapi.sql.execute.ExecutionContext;
 import org.apache.derby.impl.sql.compile.StatementNode;
 import org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext;
@@ -508,7 +510,20 @@ public class GenericStatement
 					preparedStmt.setSPSName(qt.getSPSName());
 					preparedStmt.completeCompile(qt);
 					preparedStmt.setCompileTimeWarnings(cc.getWarnings());
-				}
+
+                    // Schedule updates of any stale index statistics we may
+                    // have detected when creating the plan.
+                    TableDescriptor[] tds = qt.updateIndexStatisticsFor();
+                    if (tds.length > 0) {
+                        IndexStatisticsDaemon isd = lcc.getDataDictionary().
+                            getIndexStatsRefresher(true);
+                        if (isd != null) {
+                            for (int i=0; i < tds.length; i++) {
+                                isd.schedule(tds[i]);
+                            }
+                        }
+                    }
+                }
 				catch (StandardException e) 	// hold it, throw it
 				{
 					lcc.commitNestedTransaction();

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java?rev=1069160&r1=1069159&r2=1069160&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java Wed
Feb  9 22:52:30 2011
@@ -23,7 +23,6 @@ package	org.apache.derby.impl.sql.compil
 
 import java.util.ArrayList;
 import java.util.Vector;
-import java.sql.Types;
 
 import org.apache.derby.iapi.error.StandardException;
 import org.apache.derby.iapi.reference.SQLState;
@@ -36,9 +35,6 @@ import org.apache.derby.iapi.sql.diction
 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
 import org.apache.derby.impl.sql.CursorInfo;
 import org.apache.derby.impl.sql.CursorTableReference;
-import org.apache.derby.iapi.types.DataValueDescriptor;
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-import org.apache.derby.iapi.types.TypeId;
 
 /**
  * A CursorNode represents a result set that can be returned to a client.
@@ -70,6 +66,12 @@ public class CursorNode extends DMLState
 	private Vector	updatableColumns;
 	private FromTable updateTable;
 	private ResultColumnDescriptor[]	targetColumnDescriptors;
+    /**
+     * List of {@code TableDescriptor}s for base tables whose associated
+     * indexes should be checked for stale statistics.
+     */
+    private ArrayList statsToUpdate;
+    private boolean checkIndexStats;
 
 	//If cursor references session schema tables, save the list of those table names in savedObjects
in compiler context
 	//Following is the position of the session table names list in savedObjects in compiler
context
@@ -221,6 +223,7 @@ public class CursorNode extends DMLState
 		DataDictionary				dataDictionary;
 
 		dataDictionary = getDataDictionary();
+        checkIndexStats = (dataDictionary.getIndexStatsRefresher(true) != null);
 
 		// This is how we handle queries like: SELECT A FROM T ORDER BY B.
 		// We pull up the order by columns (if they don't appear in the SELECT
@@ -274,21 +277,11 @@ public class CursorNode extends DMLState
 			getCompilerContext().pushCurrentPrivType(Authorizer.MIN_SELECT_PRIV);
 			FromList resultSetFromList = resultSet.getFromList();
 			for (int index = 0; index < resultSetFromList.size(); index++) {
-				FromTable fromTable = (FromTable) resultSetFromList.elementAt(index);
-				if (fromTable.isPrivilegeCollectionRequired() && fromTable instanceof FromBaseTable)
-					//We ask for MIN_SELECT_PRIV requirement of the first
-					//column in the table. The first column is just a 
-					//place holder. What we really do at execution time when 
-					//we see we are looking for MIN_SELECT_PRIV privilege is
-					//as follows
-					//1)we will look for SELECT privilege at table level
-					//2)If not found, we will look for SELECT privilege on 
-					//ANY column, not necessarily the first column. But since
-					//the constructor for column privilege requires us to pass
-					//a column descriptor, we just choose the first column for
-					//MIN_SELECT_PRIV requirement.
-					getCompilerContext().addRequiredColumnPriv(fromTable.getTableDescriptor().getColumnDescriptor(1));
-			}
+                Object fromTable = resultSetFromList.elementAt(index);
+                if (fromTable instanceof FromBaseTable) {
+                    collectTablePrivsAndStats((FromBaseTable)fromTable);
+                }
+            }
 			getCompilerContext().popCurrentPrivType();
 		}
 		finally
@@ -386,6 +379,42 @@ public class CursorNode extends DMLState
 
 	}
 
+    /**
+     * Collects required privileges for all types of tables, and table
+     * descriptors for base tables whose index statistics we want to check for
+     * staleness (or to create).
+     *
+     * @param fromTable the table
+     */
+    private void collectTablePrivsAndStats(FromBaseTable fromTable) {
+        TableDescriptor td = fromTable.getTableDescriptor();
+        if (fromTable.isPrivilegeCollectionRequired()) {
+            // We ask for MIN_SELECT_PRIV requirement of the first column in
+            // the table. The first column is just a place holder. What we
+            // really do at execution time when we see we are looking for
+            // MIN_SELECT_PRIV privilege is as follows:
+            //
+            // 1) We will look for SELECT privilege at table level.
+            // 2) If not found, we will look for SELECT privilege on
+            //    ANY column, not necessarily the first column. But since
+            //    the constructor for column privilege requires us to pass
+            //    a column descriptor, we just choose the first column for
+            //    MIN_SELECT_PRIV requirement.
+            getCompilerContext().addRequiredColumnPriv(
+                    td.getColumnDescriptor(1));
+        }
+        // Save a list of base tables to check the index statistics for at a
+        // later time. We want to compute statistics for base user tables only,
+        // not for instance system tables or VTIs (see TableDescriptor for a
+        // list of all available "table types").
+        if (checkIndexStats &&
+                td.getTableType() == TableDescriptor.BASE_TABLE_TYPE) {
+            if (statsToUpdate == null) {
+                statsToUpdate = new ArrayList();
+            }
+            statsToUpdate.add(td);
+        }
+    }
 
 	/**
 	 * Return true if the node references SESSION schema tables (temporary or permanent)
@@ -828,4 +857,36 @@ public class CursorNode extends DMLState
 	{
 		return null;
 	}
+
+    /**
+     * Returns a list of base tables for which the index statistics of the
+     * associated indexes should be updated.
+     *
+     * @return A list of table descriptors (potentially empty).
+     * @throws StandardException if accessing the index descriptors of a base
+     *      table fails
+     */
+    public TableDescriptor[] updateIndexStatisticsFor()
+            throws StandardException {
+        if (!checkIndexStats || statsToUpdate == null) {
+            return EMPTY_TD_LIST;
+        }
+        // Remove table descriptors whose statistics are considered up-to-date.
+        // Iterate backwards to remove elements, chances are high the stats are
+        // mostly up-to-date (minor performance optimization to avoid copy).
+        for (int i=statsToUpdate.size() -1; i >= 0; i--) {
+            TableDescriptor td = (TableDescriptor)statsToUpdate.get(i);
+            if (td.getAndClearIndexStatsIsUpToDate()) {
+                statsToUpdate.remove(i);
+            }
+        }
+        if (statsToUpdate.isEmpty()) {
+            return EMPTY_TD_LIST;
+        } else {
+            TableDescriptor[] tmp = new TableDescriptor[statsToUpdate.size()];
+            statsToUpdate.toArray(tmp);
+            statsToUpdate.clear();
+            return tmp;
+        }
+    }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java?rev=1069160&r1=1069159&r2=1069160&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java Wed
Feb  9 22:52:30 2011
@@ -51,7 +51,6 @@ import org.apache.derby.iapi.sql.compile
 import org.apache.derby.iapi.sql.compile.JoinStrategy;
 import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;
 import org.apache.derby.iapi.sql.compile.RowOrdering;
-import org.apache.derby.iapi.sql.compile.Visitable;
 import org.apache.derby.iapi.sql.compile.Visitor;
 
 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
@@ -118,6 +117,12 @@ public class FromBaseTable extends FromT
 {
 	static final int UNSET = -1;
 
+    /**
+     * Whether or not we have checked the index statistics for staleness.
+     * Used to avoid performing the check multiple times per compilation.
+     */
+    private boolean hasCheckedIndexStats;
+
 	TableName		tableName;
 	TableDescriptor	tableDescriptor;
 
@@ -920,8 +925,19 @@ public class FromBaseTable extends FromT
 			statisticsForTable = tableDescriptor.statisticsExist(null);
 			unknownPredicateList = new PredicateList();
 			predList.copyPredicatesToOtherList(unknownPredicateList);
-
-		}
+            // If not already done, check if this table has indexes and if
+            // their statistics need to get updated.
+            if (!hasCheckedIndexStats) {
+                hasCheckedIndexStats = true;
+                // Only mark if a base table and there are indexes. Skip VTIs,
+                // system tables, subqueries etc.
+                if (tableDescriptor.getTableType() ==
+                        TableDescriptor.BASE_TABLE_TYPE &&
+                        tableDescriptor.getTotalNumberOfIndexes() > 0) {
+                    tableDescriptor.markForIndexStatsUpdate(baseRowCount());
+                }
+            }
+        }
 
 		AccessPath currentAccessPath = getCurrentAccessPath();
 		JoinStrategy currentJoinStrategy = 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java?rev=1069160&r1=1069159&r2=1069160&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java Wed
Feb  9 22:52:30 2011
@@ -21,14 +21,9 @@
 
 package	org.apache.derby.impl.sql.compile;
 
-import org.apache.derby.iapi.services.context.ContextManager;
-
 import org.apache.derby.iapi.error.StandardException;
 
 import org.apache.derby.iapi.sql.ResultDescription;
-import org.apache.derby.iapi.sql.compile.CompilerContext;
-import org.apache.derby.iapi.sql.compile.Parser;
-import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
 
 import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
@@ -65,6 +60,9 @@ import java.lang.reflect.Modifier;
 public abstract class StatementNode extends QueryTreeNode
 {
 
+    /** Cached empty list object. */
+    static final TableDescriptor[] EMPTY_TD_LIST = new TableDescriptor[0];
+
 	/**
 	 * By default, assume StatementNodes are atomic.
 	 * The rare statements that aren't atomic (e.g.
@@ -404,4 +402,20 @@ public abstract class StatementNode exte
 			throw e;
 		}
 	 }
+
+    /**
+     * Returns a list of base tables for which the index statistics of the
+     * associated indexes should be updated.
+     * <p>
+     * This default implementation always returns an empty list.
+     *
+     * @return A list of table descriptors (potentially empty).
+     * @throws StandardException if accessing the index descriptors of a base
+     *      table fails
+     */
+    public TableDescriptor[] updateIndexStatisticsFor()
+            throws StandardException {
+        // Do nothing, overridden by appropriate nodes.
+        return EMPTY_TD_LIST;
+    }
 }



Mime
View raw message