📄 frombasetable.java
字号:
** in this table times the number of times the maximum number ** of times each key can be repeated. */ double scanUniquenessFactor = optimizer.uniqueJoinWithOuterTable(baseTableRestrictionList); if (scanUniquenessFactor > 0.0) { /* ** A positive uniqueness factor means there is a unique ** outer join key. The value is the reciprocal of the ** maximum number of duplicates for each unique key ** (the duplicates can be caused by other joining tables). */ double maxRows = ((double) baseRowCount()) / scanUniquenessFactor; if (rowCount > maxRows) { /* ** The estimated row count is too high. Adjust the ** estimated cost downwards proportionately to ** match the maximum number of rows. */ newCost *= (maxRows / rowCount); } } } /* The estimated total row count may be too high */ if (tableUniquenessFactor > 0.0) { /* ** A positive uniqueness factor means there is a unique outer ** join key. The value is the reciprocal of the maximum number ** of duplicates for each unique key (the duplicates can be ** caused by other joining tables). */ double maxRows = ((double) baseRowCount()) / tableUniquenessFactor; if (rowCount > maxRows) { /* ** The estimated row count is too high. Set it to the ** maximum row count. */ rowCount = maxRows; } } costEstimate.setCost( newCost, rowCount, costEstimate.singleScanRowCount()); optimizer.trace(Optimizer.COST_OF_N_SCANS, tableNumber, 0, outerCost.rowCount(), costEstimate); /* ** Now figure in the cost of the non-qualifier predicates. ** existsBaseTables have a row count of 1 */ double rc = -1, src = -1; if (existsBaseTable) rc = src = 1; // don't factor in extraNonQualifierSelectivity in case of oneRowResultSetForSomeConglom // because "1" is the final result and the effect of other predicates already considered // beetle 4787 else if (extraNonQualifierSelectivity != 1.0d) { rc = oneRowResultSetForSomeConglom ? costEstimate.rowCount() : costEstimate.rowCount() * extraNonQualifierSelectivity; src = costEstimate.singleScanRowCount() * extraNonQualifierSelectivity; } if (rc != -1) // changed { costEstimate.setCost(costEstimate.getEstimatedCost(), rc, src); optimizer.trace(Optimizer.COST_INCLUDING_EXTRA_NONQUALIFIER_SELECTIVITY, tableNumber, 0, 0.0, costEstimate); } recomputeRowCount: if (statisticsForTable && !oneRowResultSetForSomeConglom && (statCompositeSelectivity != 1.0d)) { /* if we have statistics we should use statistics to calculate row count-- if it has been determined that this table returns one row for some conglomerate then there is no need to do this recalculation */ double compositeStatRC = initialRowCount * statCompositeSelectivity; optimizer.trace(Optimizer.COMPOSITE_SEL_FROM_STATS, 0, 0, statCompositeSelectivity, null); if (tableUniquenessFactor > 0.0) { /* If the row count from the composite statistics comes up more than what the table uniqueness factor indicates then lets stick with the current row count. */ if (compositeStatRC > (baseRowCount() * tableUniquenessFactor)) { break recomputeRowCount; } } /* set the row count and the single scan row count to the initialRowCount. initialRowCount is the product of the RC from store * RC of the outerCost. Thus RC = initialRowCount * the selectivity from stats. SingleRC = RC / outerCost.rowCount(). */ costEstimate.setCost(costEstimate.getEstimatedCost(), compositeStatRC, (existsBaseTable) ? 1 : compositeStatRC / outerCost.rowCount()); optimizer.trace(Optimizer.COST_INCLUDING_COMPOSITE_SEL_FROM_STATS, tableNumber, 0, 0.0, costEstimate); } } /* Put the base predicates back in the predicate list */ currentJoinStrategy.putBasePredicates(predList, baseTableRestrictionList); return costEstimate; } private double scanCostAfterSelectivity(double originalScanCost, double initialPositionCost, double selectivity, boolean anotherIndexUnique) throws StandardException { /* If there's another paln using unique index, its selectivity is 1/r * because we use row count 1. This plan is not unique index, so we make * selectivity at least 2/r, which is more fair, because for unique index * we don't use our selectivity estimates. Unique index also more likely * locks less rows, hence better concurrency. beetle 4787. */ if (anotherIndexUnique) { double r = baseRowCount(); if (r > 0.0) { double minSelectivity = 2.0 / r; if (minSelectivity > selectivity) selectivity = minSelectivity; } } /* initialPositionCost is the first part of the index scan cost we get above. * It's the cost of initial positioning/fetch of key. So it's unrelated to * row count of how many rows we fetch from index. We extract it here so that * we only multiply selectivity to the other part of index scan cost, which is * nearly linear, to make cost calculation more accurate and fair, especially * compared to the plan of "one row result set" (unique index). beetle 4787. */ double afterInitialCost = (originalScanCost - initialPositionCost) * selectivity; if (afterInitialCost < 0) afterInitialCost = 0; return initialPositionCost + afterInitialCost; } private void setLockingBasedOnThreshold( Optimizer optimizer, double rowsTouched) { /* In optimizer we always set it to row lock (unless there's no * start/stop key found to utilize an index, in which case we do table * lock), it's up to store to upgrade it to table lock. This makes * sense for the default read committed isolation level and update * lock. For more detail, see Beetle 4133. */ getCurrentAccessPath().setLockMode( TransactionController.MODE_RECORD); } /** @see Optimizable#isBaseTable */ public boolean isBaseTable() { return true; } /** @see Optimizable#forUpdate */ public boolean forUpdate() { /* This table is updatable if it is the * target table of an update or delete, * or it is (or was) the target table of an * updatable cursor. */ return (updateOrDelete != 0) || cursorTargetTable || getUpdateLocks; } /** @see Optimizable#initialCapacity */ public int initialCapacity() { return initialCapacity; } /** @see Optimizable#loadFactor */ public float loadFactor() { return loadFactor; } /** * @see Optimizable#memoryUsageOK */ public boolean memoryUsageOK(double rowCount, int maxMemoryPerTable) throws StandardException { return super.memoryUsageOK(singleScanRowCount, maxMemoryPerTable); } /** * @see Optimizable#isTargetTable */ public boolean isTargetTable() { return (updateOrDelete != 0); } /** * @see Optimizable#uniqueJoin */ public double uniqueJoin(OptimizablePredicateList predList) throws StandardException { double retval = -1.0; PredicateList pl = (PredicateList) predList; int numColumns = getTableDescriptor().getNumberOfColumns(); int tableNumber = getTableNumber(); // This is supposed to be an array of table numbers for the current // query block. It is used to determine whether a join is with a // correlation column, to fill in eqOuterCols properly. We don't care // about eqOuterCols, so just create a zero-length array, pretending // that all columns are correlation columns. int[] tableNumbers = new int[0]; JBitSet[] tableColMap = new JBitSet[1]; tableColMap[0] = new JBitSet(numColumns + 1); pl.checkTopPredicatesForEqualsConditions(tableNumber, null, tableNumbers, tableColMap, false); if (supersetOfUniqueIndex(tableColMap)) { retval = getBestAccessPath().getCostEstimate().singleScanRowCount(); } return retval; } /** * @see Optimizable#isOneRowScan * * @exception StandardException Thrown on error */ public boolean isOneRowScan() throws StandardException { /* EXISTS FBT will never be a 1 row scan. * Otherwise call method in super class. */ if (existsBaseTable) { return false; } return super.isOneRowScan(); } /** * @see Optimizable#legalJoinOrder */ public boolean legalJoinOrder(JBitSet assignedTableMap) { // Only an issue for EXISTS FBTs if (existsBaseTable) { /* Have all of our dependencies been satisfied? */ return assignedTableMap.contains(dependencyMap); } return true; } /** * Convert this object to a String. See comments in QueryTreeNode.java * for how this should be done for tree printing. * * @return This object as a String */ public String toString() { if (SanityManager.DEBUG) { return "tableName: " + (tableName != null ? tableName.toString() : "null") + "\n" + "tableDescriptor: " + tableDescriptor + "\n" + "updateOrDelete: " + updateOrDelete + "\n" + (tableProperties != null ? tableProperties.toString() : "null") + "\n" + "existsBaseTable: " + existsBaseTable + "\n" + "dependencyMap: " + (dependencyMap != null ? dependencyMap.toString() : "null") + "\n" + super.toString(); } else { return ""; } } /** * Does this FBT represent an EXISTS FBT. * * @return Whether or not this FBT represents * an EXISTS FBT. */ boolean getExistsBaseTable() { return existsBaseTable; } /** * Set whether or not this FBT represents an * EXISTS FBT. * * @param existsBaseTable Whether or not an EXISTS FBT. * @param dependencyMap The dependency map for the EXISTS FBT. * @param isNotExists Whether or not for NOT EXISTS, more specifically. * * @return Nothing. */ void setExistsBaseTable(boolean existsBaseTable, JBitSet dependencyMap, boolean isNotExists) { this.existsBaseTable = existsBaseTable; this.isNotExists = isNotExists; /* Set/clear the dependency map as needed */ if (existsBaseTable) { this.dependencyMap = dependencyMap; } else { this.dependencyMap = null; } } /** * Clear the bits from the dependency map when join nodes are flattened * * @param vector of bit numbers to be cleared * * @return Nothing. */ void clearDependency(Vector locations) { if (this.dependencyMap != null) { for (int i = 0; i < locations.size() ; i++) this.dependencyMap.clear(((Integer)locations.elementAt(i)).intValue()); } } /** * Set the table properties for this table. * * @param tableProperties The new table properties. * * @return Nothing. */ public void setTableProperties(Properties tableProperties) { this.tableProperties = tableProperties; } /** * Bind the table in this FromBaseTable. * This is where view resolution occurs * * @param dataDictionary The DataDictionary to use for binding * @param fromListParam FromList to use/append to. * * @return ResultSetNode The FromTable for the table or resolved view. * * @exception StandardException Thrown on error */ public ResultSetNode bindNonVTITables(DataDictionary dataDictionary, FromList fromListParam) throws StandardException { TableDescriptor tableDescriptor = bindTableDescriptor();/* if (tableDescriptor.getTableType() == TableDescriptor.VTI_TYPE) { ResultSetNode vtiNode = getNodeFactory().mapTableAsVTI(getContextManager(), tableDescriptor); return vtiNode.bindNonVTITables(dataDictionary, fromListParam); }*/ ResultColumnList derivedRCL = resultColumns; // make sure there's a restriction list restrictionList = (PredicateList) getNodeFactory().getNode( C_NodeTypes.PREDICATE_LIST, getContextMa
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -