提交 7d62d56a authored 作者: Thomas Mueller's avatar Thomas Mueller

Merge pull request #200 from svladykin/getCost2

Index.getCost accepts all joined table filters and current TableFilter index
......@@ -130,7 +130,7 @@ public class Delete extends Prepared {
condition = condition.optimize(session);
condition.createIndexConditions(session, tableFilter);
}
PlanItem item = tableFilter.getBestPlanItem(session, 1);
PlanItem item = tableFilter.getBestPlanItem(session, new TableFilter[]{tableFilter}, 0);
tableFilter.setPlanItem(item);
tableFilter.prepare();
}
......
......@@ -389,7 +389,7 @@ public class ScriptCommand extends ScriptBase {
}
private int generateInsertValues(int count, Table table) throws IOException {
PlanItem plan = table.getBestPlanItem(session, null, null, null);
PlanItem plan = table.getBestPlanItem(session, null, null, -1, null);
Index index = plan.getIndex();
Cursor cursor = index.find(session, null, null);
Column[] columns = table.getColumns();
......
......@@ -187,7 +187,7 @@ public class Update extends Prepared {
e.mapColumns(tableFilter, 0);
expressionMap.put(c, e.optimize(session));
}
PlanItem item = tableFilter.getBestPlanItem(session, 1);
PlanItem item = tableFilter.getBestPlanItem(session, new TableFilter[] {tableFilter}, 0);
tableFilter.setPlanItem(item);
tableFilter.prepare();
}
......
......@@ -5,8 +5,6 @@
*/
package org.h2.index;
import java.util.List;
import java.util.concurrent.Future;
import org.h2.api.ErrorCode;
import org.h2.engine.Constants;
import org.h2.engine.DbObject;
......@@ -152,12 +150,13 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
*
* @param masks the search mask
* @param rowCount the number of rows in the index
* @param filter the table filter
* @param filters all joined table filters
* @param filter the current table filter index
* @param sortOrder the sort order
* @return the estimated cost
*/
protected long getCostRangeIndex(int[] masks, long rowCount,
TableFilter filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder) {
rowCount += Constants.COST_ROW_OFFSET;
long cost = rowCount;
long rows = rowCount;
......@@ -201,6 +200,7 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
boolean sortOrderMatches = true;
int coveringCount = 0;
int[] sortTypes = sortOrder.getSortTypes();
TableFilter tableFilter = filters == null ? null : filters[filter];
for (int i = 0, len = sortTypes.length; i < len; i++) {
if (i >= indexColumns.length) {
// we can still use this index if we are sorting by more
......@@ -209,7 +209,7 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
// more of the order by columns
break;
}
Column col = sortOrder.getColumn(i, filter);
Column col = sortOrder.getColumn(i, tableFilter);
if (col == null) {
sortOrderMatches = false;
break;
......
......@@ -52,8 +52,8 @@ public class FunctionIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
if (masks != null) {
throw DbException.getUnsupportedException("ALIAS");
}
......
......@@ -113,8 +113,8 @@ public class HashIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
for (Column column : columns) {
int index = column.getColumnId();
int mask = masks[index];
......
......@@ -83,11 +83,12 @@ public interface Index extends SchemaObject {
* @param session the session
* @param masks per-column comparison bit masks, null means 'always false',
* see constants in IndexCondition
* @param filter the table filter
* @param filters all joined table filters
* @param filter the current table filter index
* @param sortOrder the sort order
* @return the estimated cost
*/
double getCost(Session session, int[] masks, TableFilter filter,
double getCost(Session session, int[] masks, TableFilter[] filters, int filter,
SortOrder sortOrder);
/**
......
......@@ -141,10 +141,10 @@ public class LinkedIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return 100 + getCostRangeIndex(masks, rowCount +
Constants.COST_ROW_OFFSET, filter, sortOrder);
Constants.COST_ROW_OFFSET, filters, filter, sortOrder);
}
@Override
......
......@@ -52,13 +52,13 @@ public class MetaIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
if (scan) {
return 10 * MetaTable.ROW_COUNT_APPROXIMATION;
}
return getCostRangeIndex(masks, MetaTable.ROW_COUNT_APPROXIMATION,
filter, sortOrder);
filters, filter, sortOrder);
}
@Override
......
......@@ -142,9 +142,9 @@ public class MultiVersionIndex implements Index {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
return base.getCost(session, masks, filter, sortOrder);
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return base.getCost(session, masks, filters, filter, sortOrder);
}
@Override
......
......@@ -130,8 +130,8 @@ public class NonUniqueHashIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
for (Column column : columns) {
int index = column.getColumnId();
int mask = masks[index];
......
......@@ -217,10 +217,10 @@ public class PageBtreeIndex extends PageIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return 10 * getCostRangeIndex(masks, tableData.getRowCount(session),
filter, sortOrder);
filters, filter, sortOrder);
}
@Override
......
......@@ -10,7 +10,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;
......@@ -310,8 +309,8 @@ public class PageDataIndex extends PageIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
long cost = 10 * (tableData.getRowCountApproximation() +
Constants.COST_ROW_OFFSET);
return cost;
......
......@@ -96,10 +96,10 @@ public class PageDelegateIndex extends PageIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return 10 * getCostRangeIndex(masks, mainIndex.getRowCount(session),
filter, sortOrder);
filters, filter, sortOrder);
}
@Override
......
......@@ -62,8 +62,8 @@ public class RangeIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return 1;
}
......
......@@ -174,8 +174,8 @@ public class ScanIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return tableData.getRowCountApproximation() + Constants.COST_ROW_OFFSET;
}
......
......@@ -180,7 +180,7 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
@Override
protected long getCostRangeIndex(int[] masks, long rowCount,
TableFilter filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder) {
return getCostRangeIndex(masks, rowCount, columns);
}
......@@ -208,10 +208,10 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return getCostRangeIndex(masks, table.getRowCountApproximation(),
filter, sortOrder);
filters, filter, sortOrder);
}
@Override
......
......@@ -318,10 +318,10 @@ public class TreeIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
public double getCost(Session session, int[] masks, TableFilter[] filters, int filter,
SortOrder sortOrder) {
return getCostRangeIndex(masks, tableData.getRowCountApproximation(),
filter, sortOrder);
filters, filter, sortOrder);
}
@Override
......
......@@ -115,7 +115,7 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
@Override
public synchronized double getCost(Session session, int[] masks,
TableFilter filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder) {
if (recursive) {
return 1000;
}
......
......@@ -6,7 +6,6 @@
package org.h2.mvstore.db;
import java.util.List;
import org.h2.engine.Session;
import org.h2.index.BaseIndex;
import org.h2.index.Cursor;
......@@ -89,10 +88,10 @@ public class MVDelegateIndex extends BaseIndex implements MVIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
return 10 * getCostRangeIndex(masks,
mainIndex.getRowCountApproximation(), filter, sortOrder);
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return 10 * getCostRangeIndex(masks, mainIndex.getRowCountApproximation(),
filters, filter, sortOrder);
}
@Override
......
......@@ -10,7 +10,6 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import org.h2.api.ErrorCode;
import org.h2.engine.Constants;
import org.h2.engine.Database;
......@@ -217,8 +216,8 @@ public class MVPrimaryIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
try {
long cost = 10 * (dataMap.sizeAsLongMax() + Constants.COST_ROW_OFFSET);
return cost;
......
......@@ -10,7 +10,6 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
import org.h2.api.ErrorCode;
import org.h2.engine.Database;
import org.h2.engine.Session;
......@@ -352,11 +351,11 @@ public class MVSecondaryIndex extends BaseIndex implements MVIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
try {
return 10 * getCostRangeIndex(masks,
dataMap.sizeAsLongMax(), filter, sortOrder);
return 10 * getCostRangeIndex(masks, dataMap.sizeAsLongMax(),
filters, filter, sortOrder);
} catch (IllegalStateException e) {
throw DbException.get(ErrorCode.OBJECT_CLOSED, e);
}
......
......@@ -7,7 +7,6 @@ package org.h2.mvstore.db;
import java.util.Iterator;
import java.util.List;
import org.h2.api.ErrorCode;
import org.h2.engine.Database;
import org.h2.engine.Session;
......@@ -33,7 +32,6 @@ import org.h2.value.Value;
import org.h2.value.ValueGeometry;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
......@@ -239,15 +237,15 @@ public class MVSpatialIndex extends BaseIndex implements SpatialIndex, MVIndex {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return getCostRangeIndex(masks, table.getRowCountApproximation(),
filter, sortOrder);
filters, filter, sortOrder);
}
@Override
protected long getCostRangeIndex(int[] masks, long rowCount,
TableFilter filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder) {
return SpatialTreeIndex.getCostRangeIndex(masks, rowCount, columns);
}
......
......@@ -106,9 +106,9 @@ public class Plan {
public double calculateCost(Session session) {
double cost = 1;
boolean invalidPlan = false;
int level = 1;
for (TableFilter tableFilter : allFilters) {
PlanItem item = tableFilter.getBestPlanItem(session, level++);
for (int i = 0; i < allFilters.length; i++) {
TableFilter tableFilter = allFilters[i];
PlanItem item = tableFilter.getBestPlanItem(session, allFilters, i);
planItems.put(tableFilter, item);
cost += cost * item.cost;
setEvaluatable(tableFilter, true);
......
......@@ -678,20 +678,21 @@ public abstract class Table extends SchemaObjectBase {
* @param session the session
* @param masks per-column comparison bit masks, null means 'always false',
* see constants in IndexCondition
* @param filter the table filter
* @param filters all joined table filters
* @param filter the current table filter index
* @param sortOrder the sort order
* @return the plan item
*/
public PlanItem getBestPlanItem(Session session, int[] masks,
TableFilter filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder) {
PlanItem item = new PlanItem();
item.setIndex(getScanIndex(session));
item.cost = item.getIndex().getCost(session, null, null, null);
item.cost = item.getIndex().getCost(session, null, filters, filter, null);
ArrayList<Index> indexes = getIndexes();
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, filter, sortOrder);
double cost = index.getCost(session, masks, filters, filter, sortOrder);
if (cost < item.cost) {
item.cost = cost;
item.setIndex(index);
......
......@@ -10,7 +10,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.Future;
import org.h2.command.Parser;
import org.h2.command.dml.Select;
......@@ -197,15 +196,16 @@ public class TableFilter implements ColumnResolver {
* order.
*
* @param s the session
* @param level 1 for the first table in a join, 2 for the second, and so on
* @param filters all joined table filters
* @param filter the current table filter index
* @return the best plan item
*/
public PlanItem getBestPlanItem(Session s, int level) {
public PlanItem getBestPlanItem(Session s, TableFilter[] filters, int filter) {
PlanItem item;
if (indexConditions.size() == 0) {
item = new PlanItem();
item.setIndex(table.getScanIndex(s));
item.cost = item.getIndex().getCost(s, null, null, null);
item.cost = item.getIndex().getCost(s, null, filters, filter, null);
} else {
int len = table.getColumns().length;
int[] masks = new int[len];
......@@ -225,23 +225,25 @@ public class TableFilter implements ColumnResolver {
if (select != null) {
sortOrder = select.getSortOrder();
}
item = table.getBestPlanItem(s, masks, this, sortOrder);
item = table.getBestPlanItem(s, masks, filters, filter, sortOrder);
item.setMasks(masks);
// The more index conditions, the earlier the table.
// This is to ensure joins without indexes run quickly:
// x (x.a=10); y (x.b=y.b) - see issue 113
item.cost -= item.cost * indexConditions.size() / 100 / level;
item.cost -= item.cost * indexConditions.size() / 100 / (filter + 1);
}
if (nestedJoin != null) {
setEvaluatable(nestedJoin);
item.setNestedJoinPlan(nestedJoin.getBestPlanItem(s, level));
item.setNestedJoinPlan(nestedJoin.getBestPlanItem(s, filters, filter));
// TODO optimizer: calculate cost of a join: should use separate
// expected row number and lookup cost
item.cost += item.cost * item.getNestedJoinPlan().cost;
}
if (join != null) {
setEvaluatable(join);
item.setJoinPlan(join.getBestPlanItem(s, level));
filter += nestedJoin == null ? 1 : 2;
assert filters[filter] == join;
item.setJoinPlan(join.getBestPlanItem(s, filters, filter));
// TODO optimizer: calculate cost of a join: should use separate
// expected row number and lookup cost
item.cost += item.cost * item.getJoinPlan().cost;
......
......@@ -225,9 +225,9 @@ public class TableView extends Table {
@Override
public PlanItem getBestPlanItem(Session session, int[] masks,
TableFilter filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder) {
PlanItem item = new PlanItem();
item.cost = index.getCost(session, masks, filter, sortOrder);
item.cost = index.getCost(session, masks, filters, filter, sortOrder);
final CacheKey cacheKey = new CacheKey(masks, session);
synchronized (this) {
......@@ -434,7 +434,7 @@ public class TableView extends Table {
throw DbException.get(ErrorCode.VIEW_IS_INVALID_2,
createException, getSQL(), msg);
}
PlanItem item = getBestPlanItem(session, null, null, null);
PlanItem item = getBestPlanItem(session, null, null, -1, null);
return item.getIndex();
}
......
......@@ -660,7 +660,7 @@ public class TestTableEngines extends TestBase {
@Override
public double getCost(Session session, int[] masks,
TableFilter filter, SortOrder sortOrder) {
TableFilter[] filters, int filter, SortOrder sortOrder) {
return 0;
}
......@@ -914,8 +914,8 @@ public class TestTableEngines extends TestBase {
TreeSetIndex scan = new TreeSetIndex(this, "scan",
IndexColumn.wrap(getColumns()), IndexType.createScan(false)) {
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return getRowCount(session) + Constants.COST_ROW_OFFSET;
}
};
......@@ -1205,9 +1205,9 @@ public class TestTableEngines extends TestBase {
}
@Override
public double getCost(Session session, int[] masks, TableFilter filter,
SortOrder sortOrder) {
return getCostRangeIndex(masks, set.size(), filter, sortOrder);
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
return getCostRangeIndex(masks, set.size(), filters, filter, sortOrder);
}
@Override
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论