提交 6762b765 authored 作者: S.Vladykin's avatar S.Vladykin

Batched join for SELECT sub-queries.

上级 508ed18e
......@@ -948,7 +948,7 @@ public class Select extends Query {
expressionArray = new Expression[expressions.size()];
expressions.toArray(expressionArray);
if (!session.isParsingView()) {
topTableFilter.prepareBatch(0);
topTableFilter.prepareJoinBatch(0);
}
isPrepared = true;
}
......
......@@ -27,9 +27,11 @@ public interface IndexLookupBatch {
*
* @param first the first row, or null for no limit
* @param last the last row, or null for no limit
* @return {@code false} if this search row pair is known to produce no results
* and thus the given row pair was not added
* @see Index#find(TableFilter, SearchRow, SearchRow)
*/
void addSearchRows(SearchRow first, SearchRow last);
boolean addSearchRows(SearchRow first, SearchRow last);
/**
* Check if this batch is full.
......
......@@ -24,7 +24,7 @@ public class ViewCursor implements Cursor {
private final SearchRow first, last;
private Row current;
ViewCursor(ViewIndex index, LocalResult result, SearchRow first,
public ViewCursor(ViewIndex index, LocalResult result, SearchRow first,
SearchRow last) {
this.table = index.getTable();
this.index = index;
......
......@@ -347,6 +347,10 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
param.setValue(v);
}
public Query getQuery() {
return query;
}
private Query getQuery(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) {
Query q = prepareSubQuery(querySQL, session, masks, filters, filter, sortOrder, true);
......
......@@ -363,18 +363,21 @@ public class TableFilter implements ColumnResolver {
* @param id join filter id (index of this table filter in join list)
* @return join batch if query runs over index which supports batched lookups, {@code null} otherwise
*/
public JoinBatch prepareBatch(int id) {
public JoinBatch prepareJoinBatch(int id) {
joinBatch = null;
joinFilterId = -1;
JoinBatch jb = null;
if (join != null) {
jb = join.prepareBatch(id + 1);
jb = join.prepareJoinBatch(id + 1);
}
IndexLookupBatch lookupBatch = null;
// the globally top table filter does not need batching, if isAlwaysTopTableFilter is false
// then we either not a top table filter or top table filter in a sub-query which is not
// top in outer query, thus we need to enable batching here to allow outer query run batched
// join against this sub-query
// For globally top table filter we don't need to create lookup batch, because
// currently it will not be used (this will be shown in ViewIndex.getPlanSQL()). Probably
// later on it will make sense to create it to better support X IN (...) conditions,
// but this needs to be implemented separately. If isAlwaysTopTableFilter is false
// then we either not a top table filter or top table filter in a sub-query, which
// in turn is not top in outer query, thus we need to enable batching here to allow
// outer query run batched join against this sub-query.
if (jb == null && select != null && !isAlwaysTopTableFilter(id)) {
lookupBatch = index.createLookupBatch(this);
if (lookupBatch != null) {
......@@ -387,13 +390,9 @@ public class TableFilter implements ColumnResolver {
}
joinBatch = jb;
joinFilterId = id;
// for globally top table filter we don't need to create lookup batch
// currently it will not be used, probably later on it will make sense
// to create it to better support X IN (...) conditions, but this needs
// to be implemented separately
if (lookupBatch == null && !isAlwaysTopTableFilter(id)) {
// index.createLookupBatch will be called only once because jb can be created only if
// lookupBatch is not null from the first call above
// index.createLookupBatch will be called at most once because jb can be
// created only if lookupBatch is already not null from the call above.
lookupBatch = index.createLookupBatch(this);
}
jb.register(this, lookupBatch);
......
/*
* 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.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.h2.message.DbException;
/**
* Single threaded lazy future.
*
* @param <T>
* @author Sergi Vladykin
*/
public abstract class LazyFuture<T> implements Future<T> {
private static final int S_READY = 0;
private static final int S_DONE = 1;
private static final int S_ERROR = 2;
private static final int S_CANCELED = 3;
private int state = S_READY;
private T result;
private Exception error;
/**
* Reset this future to the initial state.
*
* @return {@code false} if it was already in initial state
*/
public boolean reset() {
if (state == S_READY) {
return false;
}
state = S_READY;
result = null;
error = null;
return true;
}
/**
* Run computation and produce the result.
*
* @return the result of computation
*/
protected abstract T run() throws Exception;
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
if (state != S_READY) {
return false;
}
state = S_CANCELED;
return true;
}
@Override
public T get() throws InterruptedException, ExecutionException {
switch (state) {
case S_READY:
try {
result = run();
state = S_DONE;
} catch (Exception e) {
error = e;
if (e instanceof InterruptedException) {
throw (InterruptedException) e;
}
throw new ExecutionException(e);
} finally {
if (state != S_DONE) {
state = S_ERROR;
}
}
return result;
case S_DONE:
return result;
case S_ERROR:
throw new ExecutionException(error);
case S_CANCELED:
throw new CancellationException();
default:
throw DbException.throwInternalError();
}
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException {
return get();
}
@Override
public boolean isCancelled() {
return state == S_CANCELED;
}
@Override
public boolean isDone() {
return state == S_DONE;
}
}
......@@ -1160,10 +1160,11 @@ public class TestTableEngines extends TestBase {
}
@Override
public void addSearchRows(SearchRow first, SearchRow last) {
public boolean addSearchRows(SearchRow first, SearchRow last) {
assert !isBatchFull();
searchRows.add(first);
searchRows.add(last);
return true;
}
@Override
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论