提交 929b8335 authored 作者: Thomas Mueller's avatar Thomas Mueller

In version 1.3.172, a performance regression was introduced when fixing the…

In version 1.3.172, a performance regression was introduced when fixing the issue 389 (when there is a multi-column primary key, H2 does not seem to always pick the right index). This was related to boosting an index that matches the "order by" column list (the wrong index was used in some cases).
上级 5b3b638c
......@@ -479,7 +479,7 @@ public abstract class Query extends Prepared {
}
sortType[i] = type;
}
return new SortOrder(session.getDatabase(), index, sortType);
return new SortOrder(session.getDatabase(), index, sortType, orderList);
}
public void setOffset(Expression offset) {
......
......@@ -372,7 +372,7 @@ public class ScriptCommand extends ScriptBase {
}
private int generateInsertValues(int count, Table table) throws IOException {
PlanItem plan = table.getBestPlanItem(session, null, null);
PlanItem plan = table.getBestPlanItem(session, null, null, null);
Index index = plan.getIndex();
Cursor cursor = index.find(session, null, null);
Column[] columns = table.getColumns();
......
......@@ -775,12 +775,7 @@ public class Select extends Query {
}
// map columns in select list and condition
for (TableFilter f : filters) {
for (Expression expr : expressions) {
expr.mapColumns(f, 0);
}
if (condition != null) {
condition.mapColumns(f, 0);
}
mapColumns(f, 0);
}
if (havingIndex >= 0) {
Expression expr = expressions.get(havingIndex);
......@@ -1133,6 +1128,11 @@ public class Select extends Query {
if (condition != null) {
condition.mapColumns(resolver, level);
}
if (orderList != null) {
for (SelectOrderBy order : orderList) {
order.expression.mapColumns(resolver, level);
}
}
}
@Override
......
......@@ -216,7 +216,7 @@ public class Aggregate extends Expression {
int order = o.descending ? SortOrder.DESCENDING : SortOrder.ASCENDING;
sortType[i] = order;
}
return new SortOrder(session.getDatabase(), index, sortType);
return new SortOrder(session.getDatabase(), index, sortType, null);
}
@Override
......
......@@ -148,10 +148,11 @@ 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 sortOrder the sort order
* @return the estimated cost
*/
protected long getCostRangeIndex(int[] masks, long rowCount, SortOrder sortOrder) {
protected long getCostRangeIndex(int[] masks, long rowCount, TableFilter filter, SortOrder sortOrder) {
rowCount += Constants.COST_ROW_OFFSET;
long cost = rowCount;
long rows = rowCount;
......@@ -191,36 +192,72 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
// if the ORDER BY clause matches the ordering of this index,
// it will be cheaper than another index, so adjust the cost accordingly
if (sortOrder != null) {
int[] columnIndexes = new int[ indexColumns.length ];
int[] columnSortTypes = new int[ indexColumns.length ];
for (int i = 0, len = indexColumns.length; i < len; i++) {
columnIndexes[i] = indexColumns[i].column.getColumnId();
columnSortTypes[i] = indexColumns[i].sortType;
}
boolean sortOrderMatches = true;
int[] sortOrderQueryColumnIndexes = sortOrder.getQueryColumnIndexes();
int coveringCount = 0;
int theFollowingNeedsToBeFixedAndTested;
// see also the method Select.getSortIndex()
for (int i = 0, len = sortOrderQueryColumnIndexes.length; i < len; i++) {
if (i >= columnIndexes.length) {
// we can still use this index if we are sorting by more than it's columns
int[] sortTypes = sortOrder.getSortTypes();
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
// than it's columns, it's just that the coveringCount
// is lower than with an index that contains
// more of the order by columns
break;
}
Column col = sortOrder.getColumn(i, filter);
if (col == null) {
sortOrderMatches = false;
break;
}
if (columnIndexes[i] != sortOrderQueryColumnIndexes[i] || columnSortTypes[i] != sortOrder.getSortTypes()[i]) {
IndexColumn indexCol = indexColumns[i];
if (col != indexCol.column) {
sortOrderMatches = false;
break;
}
int sortType = sortTypes[i];
if (sortType != indexCol.sortType) {
sortOrderMatches = false;
break;
}
coveringCount++;
}
if (sortOrderMatches) {
// "coveringCount" makes sure that when we have two
// or more covering indexes, we choose the one
// that covers more
cost -= coveringCount;
}
//
// int[] columnIndexes = new int[indexColumns.length];
// int[] columnSortTypes = new int[indexColumns.length];
// for (int i = 0, len = indexColumns.length; i < len; i++) {
// columnIndexes[i] = indexColumns[i].column.getColumnId();
// columnSortTypes[i] = indexColumns[i].sortType;
// }
// boolean sortOrderMatches = true;
// int[] sortOrderQueryColumnIndexes = sortOrder.getQueryColumnIndexes();
// int coveringCount = 0;
//
// int theFollowingNeedsToBeFixedAndTested;
// // see also the method Select.getSortIndex()
// for (int i = 0, len = sortOrderQueryColumnIndexes.length; i < len; i++) {
// if (i >= columnIndexes.length) {
// // we can still use this index if we are sorting by more than it's columns
// break;
// }
// if (columnIndexes[i] != sortOrderQueryColumnIndexes[i] || columnSortTypes[i] != sortOrder.getSortTypes()[i]) {
// sortOrderMatches = false;
// break;
// }
// coveringCount++;
// }
//
// if (sortOrderMatches) {
// // "coveringCount" makes sure that when we have two
// // or more covering indexes, we choose the one
// // that covers more
// cost -= coveringCount;
// }
}
return cost;
}
......
......@@ -13,6 +13,7 @@ import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.FunctionTable;
import org.h2.table.IndexColumn;
import org.h2.table.TableFilter;
/**
* An index for a function that returns a result set. This index can only scan
......@@ -51,7 +52,7 @@ public class FunctionIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
if (masks != null) {
throw DbException.getUnsupportedException("ALIAS");
}
......
......@@ -14,6 +14,7 @@ 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;
import org.h2.util.ValueHashMap;
import org.h2.value.Value;
......@@ -112,7 +113,7 @@ public class HashIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
for (Column column : columns) {
int index = column.getColumnId();
int mask = masks[index];
......
......@@ -80,10 +80,11 @@ 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 sortOrder the sort order
* @return the estimated cost
*/
double getCost(Session session, int[] masks, SortOrder sortOrder);
double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder);
/**
* Remove the index.
......
......@@ -17,6 +17,7 @@ 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.table.TableLink;
import org.h2.util.New;
import org.h2.util.StatementBuilder;
......@@ -140,8 +141,8 @@ public class LinkedIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
return 100 + getCostRangeIndex(masks, rowCount + Constants.COST_ROW_OFFSET, sortOrder);
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
return 100 + getCostRangeIndex(masks, rowCount + Constants.COST_ROW_OFFSET, filter, sortOrder);
}
@Override
......
......@@ -15,6 +15,7 @@ import org.h2.result.SortOrder;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.MetaTable;
import org.h2.table.TableFilter;
/**
* The index implementation for meta data tables.
......@@ -52,11 +53,11 @@ public class MetaIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
if (scan) {
return 10 * MetaTable.ROW_COUNT_APPROXIMATION;
}
return getCostRangeIndex(masks, MetaTable.ROW_COUNT_APPROXIMATION, sortOrder);
return getCostRangeIndex(masks, MetaTable.ROW_COUNT_APPROXIMATION, filter, sortOrder);
}
@Override
......
......@@ -138,8 +138,8 @@ public class MultiVersionIndex implements Index {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
return base.getCost(session, masks, sortOrder);
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
return base.getCost(session, masks, filter, sortOrder);
}
@Override
......
......@@ -15,6 +15,7 @@ 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;
import org.h2.util.New;
import org.h2.util.ValueHashMap;
import org.h2.value.Value;
......@@ -129,7 +130,7 @@ public class NonUniqueHashIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
for (Column column : columns) {
int index = column.getColumnId();
int mask = masks[index];
......
......@@ -20,6 +20,7 @@ import org.h2.store.PageStore;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.RegularTable;
import org.h2.table.TableFilter;
import org.h2.util.MathUtils;
import org.h2.value.Value;
import org.h2.value.ValueNull;
......@@ -214,8 +215,8 @@ public class PageBtreeIndex extends PageIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
return 10 * getCostRangeIndex(masks, tableData.getRowCount(session), sortOrder);
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
return 10 * getCostRangeIndex(masks, tableData.getRowCount(session), filter, sortOrder);
}
@Override
......
......@@ -25,6 +25,7 @@ import org.h2.store.PageStore;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.RegularTable;
import org.h2.table.TableFilter;
import org.h2.util.MathUtils;
import org.h2.util.New;
import org.h2.value.Value;
......@@ -307,7 +308,7 @@ public class PageDataIndex extends PageIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
long cost = 10 * (tableData.getRowCountApproximation() + Constants.COST_ROW_OFFSET);
return cost;
}
......
......@@ -15,6 +15,7 @@ import org.h2.store.PageStore;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.RegularTable;
import org.h2.table.TableFilter;
/**
* An index that delegates indexing to the page data index.
......@@ -94,8 +95,8 @@ public class PageDelegateIndex extends PageIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
return 10 * getCostRangeIndex(masks, mainIndex.getRowCount(session), sortOrder);
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
return 10 * getCostRangeIndex(masks, mainIndex.getRowCount(session), filter, sortOrder);
}
@Override
......
......@@ -13,6 +13,7 @@ import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.IndexColumn;
import org.h2.table.RangeTable;
import org.h2.table.TableFilter;
/**
* An index for the SYSTEM_RANGE table.
......@@ -60,7 +61,7 @@ public class RangeIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
return 1;
}
......
......@@ -23,6 +23,7 @@ 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;
import org.h2.util.New;
/**
......@@ -170,7 +171,7 @@ public class ScanIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
return tableData.getRowCountApproximation() + Constants.COST_ROW_OFFSET;
}
......
......@@ -170,7 +170,7 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
}
@Override
protected long getCostRangeIndex(int[] masks, long rowCount, SortOrder sortOrder) {
protected long getCostRangeIndex(int[] masks, long rowCount, TableFilter filter, SortOrder sortOrder) {
rowCount += Constants.COST_ROW_OFFSET;
long cost = rowCount;
long rows = rowCount;
......@@ -188,8 +188,8 @@ public class SpatialTreeIndex extends BaseIndex implements SpatialIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
return getCostRangeIndex(masks, tableData.getRowCountApproximation(), sortOrder);
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
return getCostRangeIndex(masks, tableData.getRowCountApproximation(), filter, sortOrder);
}
@Override
......
......@@ -318,8 +318,8 @@ public class TreeIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
return getCostRangeIndex(masks, tableData.getRowCountApproximation(), sortOrder);
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
return getCostRangeIndex(masks, tableData.getRowCountApproximation(), filter, sortOrder);
}
@Override
......
......@@ -22,6 +22,7 @@ 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.table.TableView;
import org.h2.util.IntArray;
import org.h2.util.New;
......@@ -114,7 +115,7 @@ public class ViewIndex extends BaseIndex {
}
@Override
public synchronized double getCost(Session session, int[] masks, SortOrder sortOrder) {
public synchronized double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
if (recursive) {
return 1000;
}
......
......@@ -16,6 +16,7 @@ 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;
/**
* An index that delegates indexing to another index.
......@@ -73,8 +74,8 @@ public class MVDelegateIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
return 10 * getCostRangeIndex(masks, mainIndex.getRowCountApproximation(), sortOrder);
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
return 10 * getCostRangeIndex(masks, mainIndex.getRowCountApproximation(), filter, sortOrder);
}
@Override
......
......@@ -25,6 +25,7 @@ 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;
import org.h2.value.ValueArray;
import org.h2.value.ValueLong;
......@@ -195,7 +196,7 @@ public class MVPrimaryIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
try {
long cost = 10 * (dataMap.map.getSize() + Constants.COST_ROW_OFFSET);
return cost;
......
......@@ -24,6 +24,7 @@ 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.util.New;
import org.h2.value.Value;
import org.h2.value.ValueArray;
......@@ -162,9 +163,9 @@ public class MVSecondaryIndex extends BaseIndex {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
try {
return 10 * getCostRangeIndex(masks, dataMap.map.getSize(), sortOrder);
return 10 * getCostRangeIndex(masks, dataMap.map.getSize(), filter, sortOrder);
} catch (IllegalStateException e) {
throw DbException.get(ErrorCode.OBJECT_CLOSED);
}
......
......@@ -9,9 +9,14 @@ package org.h2.result;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import org.h2.command.dml.SelectOrderBy;
import org.h2.constant.SysProperties;
import org.h2.engine.Database;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn;
import org.h2.table.Column;
import org.h2.table.TableFilter;
import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils;
import org.h2.util.Utils;
......@@ -57,19 +62,29 @@ public class SortOrder implements Comparator<Value[]> {
*/
private final int[] queryColumnIndexes;
/**
* The sort type bit mask (DESCENDING, NULLS_FIRST, NULLS_LAST).
*/
private final int[] sortTypes;
/**
* The order list.
*/
private final ArrayList<SelectOrderBy> orderList;
/**
* Construct a new sort order object.
*
* @param database the database
* @param queryColumnIndexes the column index list
* @param sortType the sort order bit masks
* @param orderList the original query order list (if this is a query)
*/
public SortOrder(Database database, int[] queryColumnIndexes, int[] sortType) {
public SortOrder(Database database, int[] queryColumnIndexes, int[] sortType, ArrayList<SelectOrderBy> orderList) {
this.database = database;
this.queryColumnIndexes = queryColumnIndexes;
this.sortTypes = sortType;
this.orderList = orderList;
}
/**
......@@ -205,6 +220,33 @@ public class SortOrder implements Comparator<Value[]> {
return queryColumnIndexes;
}
/**
* Get the column for the given table filter, if the sort column is for this filter.
*
* @param index the column index (0-based)
* @param filter the table filter
* @return the column, or null
*/
public Column getColumn(int index, TableFilter filter) {
if (orderList == null) {
return null;
}
SelectOrderBy order = orderList.get(index);
Expression expr = order.expression;
expr = expr.getNonAliasExpression();
if (expr.isConstant()) {
return null;
}
if (!(expr instanceof ExpressionColumn)) {
return null;
}
ExpressionColumn exprCol = (ExpressionColumn) expr;
if (exprCol.getTableFilter() != filter) {
return null;
}
return exprCol.getColumn();
}
/**
* Get the sort order bit masks.
*
......
......@@ -631,18 +631,19 @@ 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 sortOrder the sort order
* @return the plan item
*/
public PlanItem getBestPlanItem(Session session, int[] masks, SortOrder sortOrder) {
public PlanItem getBestPlanItem(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
PlanItem item = new PlanItem();
item.setIndex(getScanIndex(session));
item.cost = item.getIndex().getCost(session, null, null);
item.cost = item.getIndex().getCost(session, null, null, 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, sortOrder);
double cost = index.getCost(session, masks, filter, sortOrder);
if (cost < item.cost) {
item.cost = cost;
item.setIndex(index);
......
......@@ -161,7 +161,7 @@ public class TableFilter implements ColumnResolver {
if (indexConditions.size() == 0) {
item = new PlanItem();
item.setIndex(table.getScanIndex(s));
item.cost = item.getIndex().getCost(s, null, null);
item.cost = item.getIndex().getCost(s, null, null, null);
} else {
int len = table.getColumns().length;
int[] masks = new int[len];
......@@ -181,7 +181,7 @@ public class TableFilter implements ColumnResolver {
if (select != null) {
sortOrder = select.getSortOrder();
}
item = table.getBestPlanItem(s, masks, sortOrder);
item = table.getBestPlanItem(s, masks, this, sortOrder);
// 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
......
......@@ -202,9 +202,9 @@ public class TableView extends Table {
}
@Override
public synchronized PlanItem getBestPlanItem(Session session, int[] masks, SortOrder sortOrder) {
public synchronized PlanItem getBestPlanItem(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
PlanItem item = new PlanItem();
item.cost = index.getCost(session, masks, sortOrder);
item.cost = index.getCost(session, masks, filter, sortOrder);
IntArray masksArray = new IntArray(masks == null ? Utils.EMPTY_INT_ARRAY : masks);
SynchronizedVerifier.check(indexCache);
ViewIndex i2 = indexCache.get(masksArray);
......@@ -374,7 +374,7 @@ public class TableView extends Table {
String msg = createException.getMessage();
throw DbException.get(ErrorCode.VIEW_IS_INVALID_2, createException, getSQL(), msg);
}
PlanItem item = getBestPlanItem(session, null, null);
PlanItem item = getBestPlanItem(session, null, null, null);
return item.getIndex();
}
......
......@@ -86,10 +86,7 @@ public class TestOptimizations extends TestBase {
"explain select name from test where name='Hello' order by name");
rs.next();
String plan = rs.getString(1);
int todoNeedsToBeFixed;
// assertTrue(plan, plan.indexOf("tableScan") >= 0);
assertContains(plan, "tableScan");
stat.execute("drop table test");
conn.close();
}
......@@ -837,9 +834,10 @@ public class TestOptimizations extends TestBase {
Connection conn = getConnection("optimizations");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE my_table(K1 INT, K2 INT, VAL VARCHAR, PRIMARY KEY(K1,K2))");
stat.execute("CREATE INDEX my_index ON my_table(K1,VAL);");
ResultSet rs = stat.executeQuery("EXPLAIN PLAN FOR SELECT * FROM my_table WHERE K1=7 ORDER BY K1,VAL");
stat.execute("CREATE TABLE my_table(K1 INT, K2 INT, VAL VARCHAR, PRIMARY KEY(K1, K2))");
stat.execute("CREATE INDEX my_index ON my_table(K1, VAL)");
ResultSet rs = stat.executeQuery(
"EXPLAIN PLAN FOR SELECT * FROM my_table WHERE K1=7 ORDER BY K1, VAL");
rs.next();
assertContains(rs.getString(1), "/* PUBLIC.MY_INDEX: K1 = 7 */");
......@@ -848,9 +846,10 @@ public class TestOptimizations extends TestBase {
// where we have two covering indexes, make sure
// we choose the one that covers more
stat.execute("CREATE TABLE my_table(K1 INT, K2 INT, VAL VARCHAR)");
stat.execute("CREATE INDEX my_index1 ON my_table(K1,K2);");
stat.execute("CREATE INDEX my_index2 ON my_table(K1,K2,VAL);");
rs = stat.executeQuery("EXPLAIN PLAN FOR SELECT * FROM my_table WHERE K1=7 ORDER BY K1,K2,VAL");
stat.execute("CREATE INDEX my_index1 ON my_table(K1, K2)");
stat.execute("CREATE INDEX my_index2 ON my_table(K1, K2, VAL)");
rs = stat.executeQuery(
"EXPLAIN PLAN FOR SELECT * FROM my_table WHERE K1=7 ORDER BY K1, K2, VAL");
rs.next();
assertContains(rs.getString(1), "/* PUBLIC.MY_INDEX2: K1 = 7 */");
......
......@@ -210,7 +210,7 @@ public class TestTableEngines extends TestBase {
}
@Override
public double getCost(Session session, int[] masks, SortOrder sortOrder) {
public double getCost(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
return 0;
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论