提交 df440fa7 authored 作者: Thomas Mueller's avatar Thomas Mueller

New database setting OPTIMIZE_IN_SELECT (enabled by default for version 1.3.x).…

New database setting OPTIMIZE_IN_SELECT (enabled by default for version 1.3.x). If enabled, IN(SELECT...) conditions are faster if there are many rows in the table or subquery.
上级 28895c0a
...@@ -20,7 +20,6 @@ import org.h2.expression.Parameter; ...@@ -20,7 +20,6 @@ import org.h2.expression.Parameter;
import org.h2.expression.ValueExpression; import org.h2.expression.ValueExpression;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.result.LocalResult; import org.h2.result.LocalResult;
import org.h2.result.ResultInterface;
import org.h2.result.ResultTarget; import org.h2.result.ResultTarget;
import org.h2.result.SortOrder; import org.h2.result.SortOrder;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
...@@ -223,7 +222,7 @@ public abstract class Query extends Prepared { ...@@ -223,7 +222,7 @@ public abstract class Query extends Prepared {
return params; return params;
} }
public ResultInterface query(int maxrows) { public LocalResult query(int maxrows) {
return query(maxrows, null); return query(maxrows, null);
} }
...@@ -234,7 +233,7 @@ public abstract class Query extends Prepared { ...@@ -234,7 +233,7 @@ public abstract class Query extends Prepared {
* @param target the target result (null will return the result) * @param target the target result (null will return the result)
* @return the result set (if the target is not set). * @return the result set (if the target is not set).
*/ */
ResultInterface query(int limit, ResultTarget target) { LocalResult query(int limit, ResultTarget target) {
fireBeforeSelectTriggers(); fireBeforeSelectTriggers();
if (!session.getDatabase().getOptimizeReuseResults()) { if (!session.getDatabase().getOptimizeReuseResults()) {
return queryWithoutCache(limit, target); return queryWithoutCache(limit, target);
......
...@@ -372,7 +372,7 @@ public class SelectUnion extends Query { ...@@ -372,7 +372,7 @@ public class SelectUnion extends Query {
return buff.toString(); return buff.toString();
} }
public ResultInterface query(int limit, ResultTarget target) { public LocalResult query(int limit, ResultTarget target) {
// union doesn't always know the parameter list of the left and right queries // union doesn't always know the parameter list of the left and right queries
return queryWithoutCache(limit, target); return queryWithoutCache(limit, target);
} }
......
...@@ -195,6 +195,13 @@ public class DbSettings extends SettingsBase { ...@@ -195,6 +195,13 @@ public class DbSettings extends SettingsBase {
*/ */
public final boolean optimizeInList = get("OPTIMIZE_IN_LIST", true); public final boolean optimizeInList = get("OPTIMIZE_IN_LIST", true);
/**
* Database setting <code>OPTIMIZE_IN_SELECT</code> (default: false).<br />
* Optimize IN(SELECT ...) comparisons. This includes
* optimization for SELECT, DELETE, and UPDATE.
*/
public final boolean optimizeInSelect = get("OPTIMIZE_IN_SELECT", Constants.VERSION_MINOR >= 3);
/** /**
* Database setting <code>OPTIMIZE_IS_NULL</code> (default: false).<br /> * Database setting <code>OPTIMIZE_IS_NULL</code> (default: false).<br />
* Use an index for condition of the form columnName IS NULL. * Use an index for condition of the form columnName IS NULL.
......
...@@ -12,7 +12,7 @@ import org.h2.engine.Database; ...@@ -12,7 +12,7 @@ import org.h2.engine.Database;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.index.IndexCondition; import org.h2.index.IndexCondition;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.result.ResultInterface; import org.h2.result.LocalResult;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -24,6 +24,7 @@ import org.h2.value.ValueNull; ...@@ -24,6 +24,7 @@ import org.h2.value.ValueNull;
* An 'in' condition with a subquery, as in WHERE ID IN(SELECT ...) * An 'in' condition with a subquery, as in WHERE ID IN(SELECT ...)
*/ */
public class ConditionInSelect extends Condition { public class ConditionInSelect extends Condition {
private Database database; private Database database;
private Expression left; private Expression left;
private Query query; private Query query;
...@@ -41,11 +42,36 @@ public class ConditionInSelect extends Condition { ...@@ -41,11 +42,36 @@ public class ConditionInSelect extends Condition {
public Value getValue(Session session) { public Value getValue(Session session) {
query.setSession(session); query.setSession(session);
ResultInterface rows = query.query(0); LocalResult rows = query.query(0);
session.addTemporaryResult(rows); session.addTemporaryResult(rows);
Value l = left.getValue(session);
if (!session.getDatabase().getSettings().optimizeInSelect) {
return getValueSlow(rows, l);
}
if (compareType != Comparison.EQUAL && compareType != Comparison.EQUAL_NULL_SAFE) {
return getValueSlow(rows, l);
}
if (rows.getRowCount() == 0) {
return ValueBoolean.get(false);
}
if (l == ValueNull.INSTANCE) {
return l;
}
if (all && rows.getRowCount() > 1) {
return ValueBoolean.get(false);
}
if (rows.containsDistinct(new Value[] { l })) {
return ValueBoolean.get(true);
}
if (rows.containsDistinct(new Value[] { ValueNull.INSTANCE })) {
return ValueNull.INSTANCE;
}
return ValueBoolean.get(false);
}
public Value getValueSlow(LocalResult rows, Value l) {
boolean hasNull = false; boolean hasNull = false;
boolean result = all; boolean result = all;
Value l = left.getValue(session);
boolean hasRow = false; boolean hasRow = false;
while (rows.next()) { while (rows.next()) {
if (!hasRow) { if (!hasRow) {
......
...@@ -270,7 +270,6 @@ public class LocalResult implements ResultInterface, ResultTarget { ...@@ -270,7 +270,6 @@ public class LocalResult implements ResultInterface, ResultTarget {
if (distinct) { if (distinct) {
if (distinctRows != null) { if (distinctRows != null) {
rows = distinctRows.values(); rows = distinctRows.values();
distinctRows = null;
} else { } else {
if (external != null && sort != null) { if (external != null && sort != null) {
// external sort // external sort
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论