提交 80398809 authored 作者: Noel Grandin's avatar Noel Grandin

Fix heavy CPU usage caused by query planner enhancement in 1.4.191

上级 a9322688
......@@ -21,6 +21,8 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>Fix extra CPU usage caused by query planner enhancement in 1.4.191
</li>
<li>improve performance of queries that use LIKE 'foo%' - 10x in the case of one of my queries
</li>
<li>Issue #231: Possible infinite loop when initializing the ObjectDataType class
......
......@@ -12,6 +12,7 @@ import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.engine.UndoLogRecord;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
import org.h2.result.ResultInterface;
import org.h2.result.Row;
import org.h2.result.RowList;
......@@ -130,7 +131,9 @@ public class Delete extends Prepared {
condition = condition.optimize(session);
condition.createIndexConditions(session, tableFilter);
}
PlanItem item = tableFilter.getBestPlanItem(session, new TableFilter[]{tableFilter}, 0);
TableFilter[] filters = new TableFilter[] { tableFilter };
PlanItem item = tableFilter.getBestPlanItem(session, filters, 0,
ExpressionVisitor.allColumnsForTableFilters(filters));
tableFilter.setPlanItem(item);
tableFilter.prepare();
}
......
......@@ -20,7 +20,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set;
import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface;
import org.h2.command.Parser;
......@@ -389,7 +388,7 @@ public class ScriptCommand extends ScriptBase {
}
private int generateInsertValues(int count, Table table) throws IOException {
PlanItem plan = table.getBestPlanItem(session, null, null, -1, null);
PlanItem plan = table.getBestPlanItem(session, null, null, -1, null, null);
Index index = plan.getIndex();
Cursor cursor = index.find(session, null, null);
Column[] columns = table.getColumns();
......
......@@ -7,7 +7,6 @@ package org.h2.command.dml;
import java.util.ArrayList;
import java.util.HashMap;
import org.h2.api.ErrorCode;
import org.h2.api.Trigger;
import org.h2.command.CommandInterface;
......@@ -15,6 +14,7 @@ import org.h2.command.Prepared;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
import org.h2.expression.Parameter;
import org.h2.expression.ValueExpression;
import org.h2.message.DbException;
......@@ -191,7 +191,9 @@ public class Update extends Prepared {
e.mapColumns(tableFilter, 0);
expressionMap.put(c, e.optimize(session));
}
PlanItem item = tableFilter.getBestPlanItem(session, new TableFilter[] {tableFilter}, 0);
TableFilter[] filters = new TableFilter[] { tableFilter };
PlanItem item = tableFilter.getBestPlanItem(session, filters, 0,
ExpressionVisitor.allColumnsForTableFilters(filters));
tableFilter.setPlanItem(item);
tableFilter.prepare();
}
......
......@@ -10,6 +10,8 @@ import org.h2.engine.DbObject;
import org.h2.table.Column;
import org.h2.table.ColumnResolver;
import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.util.New;
/**
* The visitor pattern is used to iterate through all expressions of a query
......@@ -286,4 +288,15 @@ public class ExpressionVisitor {
return type;
}
public static HashSet<Column> allColumnsForTableFilters(TableFilter[] filters) {
HashSet<Column> allColumnsSet = New.hashSet();
for (int i = 0; i < filters.length; i++) {
if (filters[i].getSelect() != null) {
filters[i].getSelect().isEverything(ExpressionVisitor.getColumnsVisitor(allColumnsSet));
}
}
return allColumnsSet;
}
}
......@@ -5,15 +5,12 @@
*/
package org.h2.index;
import java.util.Arrays;
import java.util.HashSet;
import org.h2.api.ErrorCode;
import org.h2.engine.Constants;
import org.h2.engine.DbObject;
import org.h2.engine.Mode;
import org.h2.engine.Session;
import org.h2.expression.ExpressionVisitor;
import org.h2.message.DbException;
import org.h2.message.Trace;
import org.h2.result.Row;
......@@ -25,7 +22,6 @@ import org.h2.table.IndexColumn;
import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.util.MathUtils;
import org.h2.util.New;
import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils;
import org.h2.value.Value;
......@@ -164,7 +160,7 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
*/
protected final long getCostRangeIndex(int[] masks, long rowCount,
TableFilter[] filters, int filter, SortOrder sortOrder,
boolean isScanIndex) {
boolean isScanIndex, HashSet<Column> allColumnsSet) {
rowCount += Constants.COST_ROW_OFFSET;
int totalSelectivity = 0;
long rowsCost = rowCount;
......@@ -244,27 +240,28 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
}
}
// If we have two indexes with the same cost, and one of the indexes can
// satisfy the query without needing to read from the primary table,
// satisfy the query without needing to read from the primary table (scan index),
// make that one slightly lower cost.
boolean needsToReadFromScanIndex = true;
if (!isScanIndex) {
HashSet<Column> set1 = New.hashSet();
for (int i = 0; i < filters.length; i++) {
if (filters[i].getSelect() != null) {
filters[i].getSelect().isEverything(ExpressionVisitor.getColumnsVisitor(set1));
if (!isScanIndex && allColumnsSet != null && !allColumnsSet.isEmpty()) {
boolean foundAllColumnsWeNeed = true;
for (Column c : allColumnsSet) {
if (c.getTable() == getTable()) {
boolean found = false;
for (Column c2 : columns) {
if (c == c2) {
found = true;
break;
}
}
if (!set1.isEmpty()) {
HashSet<Column> set2 = New.hashSet();
for (Column c : set1) {
if (c.getTable() == getTable()) {
set2.add(c);
if (!found) {
foundAllColumnsWeNeed = false;
break;
}
}
set2.removeAll(Arrays.asList(columns));
if (set2.isEmpty()) {
needsToReadFromScanIndex = false;
}
if (foundAllColumnsWeNeed) {
needsToReadFromScanIndex = false;
}
}
long rc;
......
......@@ -5,11 +5,13 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.Column;
import org.h2.table.FunctionTable;
import org.h2.table.IndexColumn;
import org.h2.table.TableFilter;
......@@ -53,7 +55,8 @@ public class FunctionIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
if (masks != null) {
throw DbException.getUnsupportedException("ALIAS");
}
......
......@@ -5,6 +5,7 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
......@@ -114,7 +115,8 @@ public class HashIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
for (Column column : columns) {
int index = column.getColumnId();
int mask = masks[index];
......
......@@ -5,6 +5,7 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.engine.Session;
import org.h2.result.Row;
import org.h2.result.SearchRow;
......@@ -87,7 +88,7 @@ public interface Index extends SchemaObject {
* @return the estimated cost
*/
double getCost(Session session, int[] masks, TableFilter[] filters, int filter,
SortOrder sortOrder);
SortOrder sortOrder, HashSet<Column> allColumnsSet);
/**
* Remove the index.
......
......@@ -8,6 +8,7 @@ package org.h2.index;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashSet;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.message.DbException;
......@@ -142,9 +143,10 @@ public class LinkedIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return 100 + getCostRangeIndex(masks, rowCount +
Constants.COST_ROW_OFFSET, filters, filter, sortOrder, false);
Constants.COST_ROW_OFFSET, filters, filter, sortOrder, false, allColumnsSet);
}
@Override
......
......@@ -6,6 +6,7 @@
package org.h2.index;
import java.util.ArrayList;
import java.util.HashSet;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
......@@ -53,12 +54,13 @@ public class MetaIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
if (scan) {
return 10 * MetaTable.ROW_COUNT_APPROXIMATION;
}
return getCostRangeIndex(masks, MetaTable.ROW_COUNT_APPROXIMATION,
filters, filter, sortOrder, false);
filters, filter, sortOrder, false, allColumnsSet);
}
@Override
......
......@@ -6,6 +6,7 @@
package org.h2.index;
import java.util.ArrayList;
import java.util.HashSet;
import org.h2.api.ErrorCode;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
......@@ -141,8 +142,9 @@ public class MultiVersionIndex implements Index {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return base.getCost(session, masks, filters, filter, sortOrder);
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return base.getCost(session, masks, filters, filter, sortOrder, allColumnsSet);
}
@Override
......
......@@ -6,6 +6,7 @@
package org.h2.index;
import java.util.ArrayList;
import java.util.HashSet;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
......@@ -131,7 +132,8 @@ public class NonUniqueHashIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
for (Column column : columns) {
int index = column.getColumnId();
int mask = masks[index];
......
......@@ -5,6 +5,7 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.api.ErrorCode;
import org.h2.engine.Constants;
import org.h2.engine.Session;
......@@ -218,9 +219,10 @@ public class PageBtreeIndex extends PageIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return 10 * getCostRangeIndex(masks, tableData.getRowCount(session),
filters, filter, sortOrder, false);
filters, filter, sortOrder, false, allColumnsSet);
}
@Override
......
......@@ -310,7 +310,8 @@ public class PageDataIndex extends PageIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
long cost = 10 * (tableData.getRowCountApproximation() +
Constants.COST_ROW_OFFSET);
return cost;
......
......@@ -5,6 +5,7 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
......@@ -97,9 +98,10 @@ public class PageDelegateIndex extends PageIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return 10 * getCostRangeIndex(masks, mainIndex.getRowCount(session),
filters, filter, sortOrder, false);
filters, filter, sortOrder, false, allColumnsSet);
}
@Override
......
......@@ -5,11 +5,13 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.RangeTable;
import org.h2.table.TableFilter;
......@@ -63,7 +65,8 @@ public class RangeIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return 1;
}
......
......@@ -11,7 +11,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.h2.api.ErrorCode;
import org.h2.engine.Constants;
import org.h2.engine.Session;
......@@ -175,7 +174,8 @@ public class ScanIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return tableData.getRowCountApproximation() + Constants.COST_ROW_OFFSET;
}
......
......@@ -5,8 +5,8 @@
*/
package org.h2.index;
import java.util.HashSet;
import java.util.Iterator;
import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.message.DbException;
......@@ -24,7 +24,6 @@ import org.h2.table.TableFilter;
import org.h2.value.Value;
import org.h2.value.ValueGeometry;
import org.h2.value.ValueNull;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
......@@ -203,7 +202,8 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return getCostRangeIndex(masks, table.getRowCountApproximation(), columns);
}
......
......@@ -5,12 +5,14 @@
*/
package org.h2.index;
import java.util.HashSet;
import org.h2.engine.Session;
import org.h2.engine.SysProperties;
import org.h2.message.DbException;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.RegularTable;
import org.h2.table.TableFilter;
......@@ -319,9 +321,9 @@ public class TreeIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks, TableFilter[] filters, int filter,
SortOrder sortOrder) {
SortOrder sortOrder, HashSet<Column> allColumnsSet) {
return getCostRangeIndex(masks, tableData.getRowCountApproximation(),
filters, filter, sortOrder, false);
filters, filter, sortOrder, false, allColumnsSet);
}
@Override
......
......@@ -6,6 +6,7 @@
package org.h2.index;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import org.h2.api.ErrorCode;
import org.h2.command.Prepared;
......@@ -147,7 +148,8 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return recursive ? 1000 : query.getCost();
}
......
......@@ -5,6 +5,7 @@
*/
package org.h2.mvstore.db;
import java.util.HashSet;
import java.util.List;
import org.h2.engine.Session;
import org.h2.index.BaseIndex;
......@@ -89,9 +90,10 @@ public class MVDelegateIndex extends BaseIndex implements MVIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return 10 * getCostRangeIndex(masks, mainIndex.getRowCountApproximation(),
filters, filter, sortOrder, true);
filters, filter, sortOrder, true, allColumnsSet);
}
@Override
......
......@@ -7,6 +7,7 @@ package org.h2.mvstore.db;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
......@@ -216,10 +217,11 @@ public class MVPrimaryIndex extends BaseIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
try {
return 10 * getCostRangeIndex(masks, dataMap.sizeAsLongMax(),
filters, filter, sortOrder, true);
filters, filter, sortOrder, true, allColumnsSet);
} catch (IllegalStateException e) {
throw DbException.get(ErrorCode.OBJECT_CLOSED, e);
}
......
......@@ -7,6 +7,7 @@ package org.h2.mvstore.db;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
......@@ -352,10 +353,11 @@ public class MVSecondaryIndex extends BaseIndex implements MVIndex {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
try {
return 10 * getCostRangeIndex(masks, dataMap.sizeAsLongMax(),
filters, filter, sortOrder, false);
filters, filter, sortOrder, false, allColumnsSet);
} catch (IllegalStateException e) {
throw DbException.get(ErrorCode.OBJECT_CLOSED, e);
}
......
......@@ -5,6 +5,7 @@
*/
package org.h2.mvstore.db;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.h2.api.ErrorCode;
......@@ -26,6 +27,7 @@ import org.h2.mvstore.rtree.SpatialKey;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.TableFilter;
import org.h2.value.Value;
......@@ -238,7 +240,8 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
@Override
public double getCost(Session session, int[] masks, TableFilter[] filters,
int filter, SortOrder sortOrder) {
int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return SpatialTreeIndex.getCostRangeIndex(masks,
table.getRowCountApproximation(), columns);
}
......
......@@ -8,6 +8,7 @@ package org.h2.table;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
......@@ -112,12 +113,13 @@ public class Plan {
}
double cost = 1;
boolean invalidPlan = false;
final HashSet<Column> allColumnsSet = ExpressionVisitor.allColumnsForTableFilters(allFilters);
for (int i = 0; i < allFilters.length; i++) {
TableFilter tableFilter = allFilters[i];
if (t.isDebugEnabled()) {
t.debug("Plan : for table filter {0}", tableFilter);
}
PlanItem item = tableFilter.getBestPlanItem(session, allFilters, i);
PlanItem item = tableFilter.getBestPlanItem(session, allFilters, i, allColumnsSet);
planItems.put(tableFilter, item);
if (t.isDebugEnabled()) {
t.debug("Plan : best plan item cost {0} index {1}",
......
......@@ -246,12 +246,13 @@ public abstract class Table extends SchemaObjectBase {
* @param session the session
* @param masks the search mask
* @param filters the table filters
* @param filter the filer index
* @param filter the filter index
* @param sortOrder the sort order
* @return the scan index
*/
public Index getScanIndex(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return getScanIndex(session);
}
......@@ -704,10 +705,11 @@ public abstract class Table extends SchemaObjectBase {
* @return the plan item
*/
public PlanItem getBestPlanItem(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
PlanItem item = new PlanItem();
item.setIndex(getScanIndex(session));
item.cost = item.getIndex().getCost(session, null, filters, filter, null);
item.cost = item.getIndex().getCost(session, null, filters, filter, null, allColumnsSet);
Trace t = session.getTrace();
if (t.isDebugEnabled()) {
t.debug("Table : potential plan item cost {0} index {1}",
......@@ -717,7 +719,7 @@ public abstract class Table extends SchemaObjectBase {
if (indexes != null && masks != null) {
for (int i = 1, size = indexes.size(); i < size; i++) {
Index index = indexes.get(i);
double cost = index.getCost(session, masks, filters, filter, sortOrder);
double cost = index.getCost(session, masks, filters, filter, sortOrder, allColumnsSet);
if (t.isDebugEnabled()) {
t.debug("Table : potential plan item cost {0} index {1}",
cost, index.getPlanSQL());
......
......@@ -6,7 +6,7 @@
package org.h2.table;
import java.util.ArrayList;
import java.util.HashSet;
import org.h2.command.Parser;
import org.h2.command.dml.Select;
import org.h2.engine.Right;
......@@ -186,7 +186,8 @@ public class TableFilter implements ColumnResolver {
* @param filter the current table filter index
* @return the best plan item
*/
public PlanItem getBestPlanItem(Session s, TableFilter[] filters, int filter) {
public PlanItem getBestPlanItem(Session s, TableFilter[] filters, int filter,
HashSet<Column> allColumnsSet) {
PlanItem item1 = null;
SortOrder sortOrder = null;
if (select != null) {
......@@ -194,8 +195,8 @@ public class TableFilter implements ColumnResolver {
}
if (indexConditions.size() == 0) {
item1 = new PlanItem();
item1.setIndex(table.getScanIndex(s, null, filters, filter, sortOrder));
item1.cost = item1.getIndex().getCost(s, null, filters, filter, sortOrder);
item1.setIndex(table.getScanIndex(s, null, filters, filter, sortOrder, allColumnsSet));
item1.cost = item1.getIndex().getCost(s, null, filters, filter, sortOrder, allColumnsSet);
}
int len = table.getColumns().length;
int[] masks = new int[len];
......@@ -211,7 +212,7 @@ public class TableFilter implements ColumnResolver {
}
}
}
PlanItem item = table.getBestPlanItem(s, masks, filters, filter, sortOrder);
PlanItem item = table.getBestPlanItem(s, masks, filters, filter, sortOrder, allColumnsSet);
item.setMasks(masks);
// The more index conditions, the earlier the table.
// This is to ensure joins without indexes run quickly:
......@@ -224,7 +225,7 @@ public class TableFilter implements ColumnResolver {
if (nestedJoin != null) {
setEvaluatable(nestedJoin);
item.setNestedJoinPlan(nestedJoin.getBestPlanItem(s, filters, filter));
item.setNestedJoinPlan(nestedJoin.getBestPlanItem(s, filters, filter, allColumnsSet));
// TODO optimizer: calculate cost of a join: should use separate
// expected row number and lookup cost
item.cost += item.cost * item.getNestedJoinPlan().cost;
......@@ -234,7 +235,7 @@ public class TableFilter implements ColumnResolver {
do {
filter++;
} while (filters[filter] != join);
item.setJoinPlan(join.getBestPlanItem(s, filters, filter));
item.setJoinPlan(join.getBestPlanItem(s, filters, filter, allColumnsSet));
// TODO optimizer: calculate cost of a join: should use separate
// expected row number and lookup cost
item.cost += item.cost * item.getJoinPlan().cost;
......
......@@ -235,7 +235,8 @@ public class TableView extends Table {
@Override
public PlanItem getBestPlanItem(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
final CacheKey cacheKey = new CacheKey(masks, this);
Map<Object, ViewIndex> indexCache = session.getViewIndexCache(topQuery != null);
ViewIndex i = indexCache.get(cacheKey);
......@@ -244,7 +245,7 @@ public class TableView extends Table {
indexCache.put(cacheKey, i);
}
PlanItem item = new PlanItem();
item.cost = i.getCost(session, masks, filters, filter, sortOrder);
item.cost = i.getCost(session, masks, filters, filter, sortOrder, allColumnsSet);
item.setIndex(i);
return item;
}
......@@ -439,18 +440,19 @@ public class TableView extends Table {
@Override
public Index getScanIndex(Session session) {
return getBestPlanItem(session, null, null, -1, null).getIndex();
return getBestPlanItem(session, null, null, -1, null, null).getIndex();
}
@Override
public Index getScanIndex(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
if (createException != null) {
String msg = createException.getMessage();
throw DbException.get(ErrorCode.VIEW_IS_INVALID_2,
createException, getSQL(), msg);
}
PlanItem item = getBestPlanItem(session, masks, filters, filter, sortOrder);
PlanItem item = getBestPlanItem(session, masks, filters, filter, sortOrder, allColumnsSet);
return item.getIndex();
}
......
......@@ -14,6 +14,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
......@@ -40,6 +41,7 @@ import org.h2.message.DbException;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.SubQueryInfo;
import org.h2.table.Table;
......@@ -901,7 +903,8 @@ public class TestTableEngines extends TestBase {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return 0;
}
......@@ -1157,10 +1160,11 @@ public class TestTableEngines extends TestBase {
IndexColumn.wrap(getColumns()), IndexType.createScan(false)) {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
doTests(session);
return getCostRangeIndex(masks, getRowCount(session), filters,
filter, sortOrder, true);
filter, sortOrder, true, allColumnsSet);
}
};
......@@ -1505,9 +1509,9 @@ public class TestTableEngines extends TestBase {
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder, HashSet<Column> allColumnsSet) {
doTests(session);
return getCostRangeIndex(masks, set.size(), filters, filter, sortOrder, false);
return getCostRangeIndex(masks, set.size(), filters, filter, sortOrder, false, allColumnsSet);
}
@Override
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论