提交 8a96db5a authored 作者: S.Vladykin's avatar S.Vladykin

Batching support for index lookups and batched joins.

上级 b2a70c1c
......@@ -17,7 +17,7 @@ import org.h2.value.ValueNull;
* Represents a single SQL statements.
* It wraps a prepared statement.
*/
class CommandContainer extends Command {
public class CommandContainer extends Command {
private Prepared prepared;
private boolean readOnlyKnown;
......
......@@ -5,6 +5,10 @@
*/
package org.h2.index;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Future;
import org.h2.api.ErrorCode;
import org.h2.engine.Constants;
import org.h2.engine.DbObject;
......@@ -424,4 +428,14 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
// ignore
}
@Override
public int getPreferedLookupBatchSize() {
// No batched lookups supported by default.
return 0;
}
@Override
public List<Future<Cursor>> findBatched(TableFilter filter, List<SearchRow> firstLastPairs) {
throw DbException.throwInternalError("Must not be called if getPreferedLookupBatchSize() is 0.");
}
}
......@@ -5,6 +5,9 @@
*/
package org.h2.index;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Future;
import org.h2.engine.Session;
import org.h2.result.Row;
import org.h2.result.SearchRow;
......@@ -255,5 +258,29 @@ public interface Index extends SchemaObject {
* @param sortedInsertMode the new value
*/
void setSortedInsertMode(boolean sortedInsertMode);
/**
* If this index can do batched lookups, it may return it's preferred batch size,
* otherwise it must return 0.
*
* @return preferred batch size or 0 if lookup batching is not supported
* @see #findBatched(TableFilter, Collection)
*/
int getPreferedLookupBatchSize();
/**
* Do batched lookup over the given collection of {@link SearchRow} pairs as in
* {@link #find(TableFilter, SearchRow, SearchRow)}.
* <br/><br/>
* Correct implementation must always return number of future cursors equal to
* {@code firstLastPairs.size() / 2}. Instead of {@link Future} containing empty
* {@link Cursor} it is possible to put {@code null} in result list.
*
* @param filter the table filter
* @param firstLastPairs List of batched search row pairs as in
* {@link #find(TableFilter, SearchRow, SearchRow)}, the collection will be reused by H2,
* thus it makes sense to defensively copy contents if needed.
* @return batched cursors for respective search row pairs in the same order
*/
List<Future<Cursor>> findBatched(TableFilter filter, List<SearchRow> firstLastPairs);
}
......@@ -68,12 +68,12 @@ public class IndexCursor implements Cursor {
}
/**
* Re-evaluate the start and end values of the index search for rows.
*
* @param s the session
* @param indexConditions the index conditions
* Prepare this index cursor to make a lookup in index.
*
* @param s Session.
* @param indexConditions Index conditions.
*/
public void find(Session s, ArrayList<IndexCondition> indexConditions) {
public void prepare(Session s, ArrayList<IndexCondition> indexConditions) {
this.session = s;
alwaysFalse = false;
start = end = null;
......@@ -148,6 +148,16 @@ public class IndexCursor implements Cursor {
}
}
}
}
/**
* Re-evaluate the start and end values of the index search for rows.
*
* @param s the session
* @param indexConditions the index conditions
*/
public void find(Session s, ArrayList<IndexCondition> indexConditions) {
prepare(s, indexConditions);
if (inColumn != null) {
return;
}
......@@ -251,6 +261,24 @@ public class IndexCursor implements Cursor {
public boolean isAlwaysFalse() {
return alwaysFalse;
}
/**
* Get start search row.
*
* @return search row
*/
public SearchRow getStart() {
return start;
}
/**
* Get end search row.
*
* @return search row
*/
public SearchRow getEnd() {
return end;
}
@Override
public Row get() {
......
......@@ -6,7 +6,10 @@
package org.h2.index;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Future;
import org.h2.api.ErrorCode;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
......@@ -387,4 +390,13 @@ public class MultiVersionIndex implements Index {
delta.setSortedInsertMode(sortedInsertMode);
}
@Override
public int getPreferedLookupBatchSize() {
return 0;
}
@Override
public List<Future<Cursor>> findBatched(TableFilter filter, List<SearchRow> firstLastPairs) {
throw DbException.throwInternalError("Must never be called.");
}
}
......@@ -6,6 +6,7 @@
package org.h2.table;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
......@@ -104,7 +105,7 @@ public abstract class Table extends SchemaObjectBase {
private ArrayList<TableView> views;
private boolean checkForeignKeyConstraints = true;
private boolean onCommitDrop, onCommitTruncate;
private Row nullRow;
private volatile Row nullRow;
public Table(Schema schema, int id, String name, boolean persistIndexes,
boolean persistData) {
......@@ -616,14 +617,15 @@ public abstract class Table extends SchemaObjectBase {
return new SimpleRow(new Value[columns.length]);
}
synchronized Row getNullRow() {
if (nullRow == null) {
nullRow = new Row(new Value[columns.length], 1);
for (int i = 0; i < columns.length; i++) {
nullRow.setValue(i, ValueNull.INSTANCE);
}
Row getNullRow() {
Row row = nullRow;
if (row == null) {
// Here can be concurrently produced more than one row, but it must be ok.
Value[] values = new Value[columns.length];
Arrays.fill(values, ValueNull.INSTANCE);
nullRow = row = new Row(values, 1);
}
return nullRow;
return row;
}
public Column[] getColumns() {
......
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.util;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Future which is already done.
*
* @param <T> Result value.
* @author Sergi Vladykin
*/
public class DoneFuture<T> implements Future<T> {
final T x;
public DoneFuture(T x) {
this.x = x;
}
@Override
public T get() throws InterruptedException, ExecutionException {
return x;
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return x;
}
@Override
public boolean isDone() {
return true;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public String toString() {
return "DoneFuture->" + x;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论