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

Batched join for SELECT sub-queries.

上级 508ed18e
...@@ -948,7 +948,7 @@ public class Select extends Query { ...@@ -948,7 +948,7 @@ public class Select extends Query {
expressionArray = new Expression[expressions.size()]; expressionArray = new Expression[expressions.size()];
expressions.toArray(expressionArray); expressions.toArray(expressionArray);
if (!session.isParsingView()) { if (!session.isParsingView()) {
topTableFilter.prepareBatch(0); topTableFilter.prepareJoinBatch(0);
} }
isPrepared = true; isPrepared = true;
} }
......
...@@ -27,9 +27,11 @@ public interface IndexLookupBatch { ...@@ -27,9 +27,11 @@ public interface IndexLookupBatch {
* *
* @param first the first row, or null for no limit * @param first the first row, or null for no limit
* @param last the last 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) * @see Index#find(TableFilter, SearchRow, SearchRow)
*/ */
void addSearchRows(SearchRow first, SearchRow last); boolean addSearchRows(SearchRow first, SearchRow last);
/** /**
* Check if this batch is full. * Check if this batch is full.
......
...@@ -24,7 +24,7 @@ public class ViewCursor implements Cursor { ...@@ -24,7 +24,7 @@ public class ViewCursor implements Cursor {
private final SearchRow first, last; private final SearchRow first, last;
private Row current; private Row current;
ViewCursor(ViewIndex index, LocalResult result, SearchRow first, public ViewCursor(ViewIndex index, LocalResult result, SearchRow first,
SearchRow last) { SearchRow last) {
this.table = index.getTable(); this.table = index.getTable();
this.index = index; this.index = index;
......
...@@ -347,6 +347,10 @@ public class ViewIndex extends BaseIndex implements SpatialIndex { ...@@ -347,6 +347,10 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
param.setValue(v); param.setValue(v);
} }
public Query getQuery() {
return query;
}
private Query getQuery(Session session, int[] masks, private Query getQuery(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder) { TableFilter[] filters, int filter, SortOrder sortOrder) {
Query q = prepareSubQuery(querySQL, session, masks, filters, filter, sortOrder, true); Query q = prepareSubQuery(querySQL, session, masks, filters, filter, sortOrder, true);
......
...@@ -363,18 +363,21 @@ public class TableFilter implements ColumnResolver { ...@@ -363,18 +363,21 @@ public class TableFilter implements ColumnResolver {
* @param id join filter id (index of this table filter in join list) * @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 * @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; joinBatch = null;
joinFilterId = -1; joinFilterId = -1;
JoinBatch jb = null; JoinBatch jb = null;
if (join != null) { if (join != null) {
jb = join.prepareBatch(id + 1); jb = join.prepareJoinBatch(id + 1);
} }
IndexLookupBatch lookupBatch = null; IndexLookupBatch lookupBatch = null;
// the globally top table filter does not need batching, if isAlwaysTopTableFilter is false // For globally top table filter we don't need to create lookup batch, because
// then we either not a top table filter or top table filter in a sub-query which is not // currently it will not be used (this will be shown in ViewIndex.getPlanSQL()). Probably
// top in outer query, thus we need to enable batching here to allow outer query run batched // later on it will make sense to create it to better support X IN (...) conditions,
// join against this sub-query // 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)) { if (jb == null && select != null && !isAlwaysTopTableFilter(id)) {
lookupBatch = index.createLookupBatch(this); lookupBatch = index.createLookupBatch(this);
if (lookupBatch != null) { if (lookupBatch != null) {
...@@ -387,13 +390,9 @@ public class TableFilter implements ColumnResolver { ...@@ -387,13 +390,9 @@ public class TableFilter implements ColumnResolver {
} }
joinBatch = jb; joinBatch = jb;
joinFilterId = id; 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)) { if (lookupBatch == null && !isAlwaysTopTableFilter(id)) {
// index.createLookupBatch will be called only once because jb can be created only if // index.createLookupBatch will be called at most once because jb can be
// lookupBatch is not null from the first call above // created only if lookupBatch is already not null from the call above.
lookupBatch = index.createLookupBatch(this); lookupBatch = index.createLookupBatch(this);
} }
jb.register(this, lookupBatch); 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 { ...@@ -1160,10 +1160,11 @@ public class TestTableEngines extends TestBase {
} }
@Override @Override
public void addSearchRows(SearchRow first, SearchRow last) { public boolean addSearchRows(SearchRow first, SearchRow last) {
assert !isBatchFull(); assert !isBatchFull();
searchRows.add(first); searchRows.add(first);
searchRows.add(last); searchRows.add(last);
return true;
} }
@Override @Override
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论