Skip to content

Commit

Permalink
MONDRIAN: improved constraint optimization, now use the right schema …
Browse files Browse the repository at this point in the history
…reader. ColumnConstraint introduced, because a constraint is now usually of type RolapMember.

[git-p4: depot-paths = "//open/mondrian/": change = 3103]
  • Loading branch information
hhaas committed Jan 26, 2005
1 parent 2a0ea8e commit d41d8cb
Show file tree
Hide file tree
Showing 12 changed files with 153 additions and 106 deletions.
11 changes: 11 additions & 0 deletions src/main/mondrian/olap/MondrianResource.xml
Expand Up @@ -384,6 +384,17 @@
<text>Input line is not a valid INSERT statement; line {0,number}: {1}.</text>
</exception>

<!-- ====================================================================== -->
<!-- Runtime limit overflow -->

<message id="600010" name="LimitExceededDuringCrossjoin">
<text>Size of CrossJoin result ({0,number}) exceeded limit ({1,number})</text>
</message>

<message id="600020" name="MemberFetchLimitExceeded">
<text>Number of Members to be read exceeded limit ({0,number})</text>
</message>

<!-- End of last error section ============================================ -->

</resourceBundle>
Expand Down
20 changes: 11 additions & 9 deletions src/main/mondrian/olap/fun/CrossJoinFunDef.java
Expand Up @@ -36,25 +36,27 @@ public Object evaluate(Evaluator evaluator, Exp[] args) {

// optimize nonempty(crossjoin(a,b)) ==
// nonempty(crossjoin(nonempty(a),nonempty(b))
long size = (long)set0.size() * (long)set1.size();

// throw an exeption, if the crossjoin gets too large
int limit = MondrianProperties.instance().getResultLimit();
if ( limit > 0 && limit < size ) {
// result limit exceeded, throw an exception
String msg = "Crossjoin result limit(" +limit +") exceeded; size=" + size;
throw new ResultLimitExceeded(msg);
}

long size = (long)set0.size() * (long)set1.size();
if (size > 1000 && evaluator.isNonEmpty()) {
set0 = nonEmptyList(evaluator, set0);
set1 = nonEmptyList(evaluator, set1);
size = (long)set0.size() * (long)set1.size();
}

if (set0.isEmpty() || set1.isEmpty()) {
return Collections.EMPTY_LIST;
}

// throw an exeption, if the crossjoin gets too large
int limit = MondrianProperties.instance().getResultLimit();
if ( limit > 0 && limit < size ) {
// result limit exceeded, throw an exception
String msg = MondrianResource.instance().
getLimitExceededDuringCrossjoin(new Long(size), new Long(limit));
throw new ResultLimitExceeded(msg);
}

boolean neitherSideIsTuple = true;
int arity0 = 1,
arity1 = 1;
Expand Down
17 changes: 9 additions & 8 deletions src/main/mondrian/rolap/FastBatchingCellReader.java
Expand Up @@ -4,6 +4,7 @@
import mondrian.olap.Util;
import mondrian.rolap.agg.AggregationManager;
import mondrian.rolap.agg.CellRequest;
import mondrian.rolap.agg.ColumnConstraint;

import java.util.*;

Expand Down Expand Up @@ -69,14 +70,14 @@ void recordCellRequest(CellRequest request) {
batch.add(request);
}

boolean loadAggregations(Evaluator evaluator) {
boolean loadAggregations() {
//System.out.println("requestCount = " + requestCount);
long t1 = System.currentTimeMillis();
requestCount = 0;
if (batches.isEmpty())
return false;
for (Iterator it = batches.values().iterator(); it.hasNext();)
((Batch) it.next()).loadAggregation(evaluator);
((Batch) it.next()).loadAggregation();
batches.clear();
long t2 = System.currentTimeMillis();
if (false) {
Expand Down Expand Up @@ -114,17 +115,17 @@ public void add(CellRequest request) {
}
}

void loadAggregation(Evaluator evaluator) {
void loadAggregation() {
long t1 = System.currentTimeMillis();
AggregationManager aggmgr = (AggregationManager) AggregationManager.instance();
Object[][] constraintses = new Object[columns.length][];
ColumnConstraint[][] constraintses = new ColumnConstraint[columns.length][];
for (int j = 0; j < columns.length; j++) {
Object[] constraints;
ColumnConstraint[] constraints;
Set valueSet = valueSets[j];
if (valueSet == null) {
constraints = null;
} else {
constraints = valueSet.toArray();
constraints = (ColumnConstraint[]) valueSet.toArray(new ColumnConstraint[0]);
}
constraintses[j] = constraints;
}
Expand Down Expand Up @@ -154,13 +155,13 @@ void loadAggregation(Evaluator evaluator) {
}
RolapStar.Measure[] measures =
(RolapStar.Measure[]) distinctMeasuresList.toArray(new RolapStar.Measure[0]);
aggmgr.loadAggregation(measures, columns, constraintses, pinnedSegments, evaluator);
aggmgr.loadAggregation(measures, columns, constraintses, pinnedSegments);
}
final int measureCount = measuresList.size();
if (measureCount > 0) {
RolapStar.Measure[] measures =
(RolapStar.Measure[]) measuresList.toArray(new RolapStar.Measure[measureCount]);
aggmgr.loadAggregation(measures, columns, constraintses, pinnedSegments, evaluator);
aggmgr.loadAggregation(measures, columns, constraintses, pinnedSegments);
}
long t2 = System.currentTimeMillis();
if (false) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/mondrian/rolap/RolapResult.java
Expand Up @@ -72,7 +72,7 @@ class RolapResult extends ResultBase
evaluator.cellReader = batchingReader;
axisResult = executeAxis(evaluator.push(), axis);
evaluator.clearExpResultCache();
if (!batchingReader.loadAggregations(evaluator)) {
if (!batchingReader.loadAggregations()) {
break;
}
if (attempt++ > MAX_AGGREGATION_PASS_COUNT) {
Expand Down Expand Up @@ -195,7 +195,7 @@ private void executeBody(Query query) {
// Retrieve the aggregations collected.
//
//
if (!batchingReader.loadAggregations(evaluator)) {
if (!batchingReader.loadAggregations()) {
// We got all of the cells we needed, so the result must be
// correct.
return;
Expand Down
35 changes: 11 additions & 24 deletions src/main/mondrian/rolap/RolapStar.java
Expand Up @@ -17,6 +17,7 @@
import mondrian.olap.MondrianResource;
import mondrian.rolap.agg.Aggregation;
import mondrian.rolap.agg.CellRequest;
import mondrian.rolap.agg.ColumnConstraint;
import mondrian.rolap.sql.SqlQuery;

import javax.sql.DataSource;
Expand Down Expand Up @@ -336,13 +337,9 @@ public String getExpression(SqlQuery query) {
return expression.getExpression(query);
}

String quoteValue(Object value)
String quoteValue(Object o)
{
String s;
if (value instanceof RolapMember)
s = ((RolapMember)value).getSqlKey().toString();
else
s = value.toString();
String s = o.toString();
if (isNumeric) {
return s;
} else {
Expand Down Expand Up @@ -444,38 +441,28 @@ private int getCardinality(Connection jdbcConnection) {
*
* <li>String values: <code>foo.bar in ('a', 'b', 'c')</code></li></ul>
*/
public String createInExpr(String expr, Object[] constraints) {
public String createInExpr(String expr, ColumnConstraint[] constraints) {
if (constraints.length == 1) {
final Object constraint = constraints[0];
Object key;
if (constraint instanceof RolapMember) {
key = ((RolapMember)constraint).getSqlKey();
} else {
key = constraint;
}
final ColumnConstraint constraint = constraints[0];
Object key = constraint.getValue();
if (key != RolapUtil.sqlNullValue) {
return expr + " = " + quoteValue(constraint);
return expr + " = " + quoteValue(key);
}
}
int notNullCount = 0;
StringBuffer sb = new StringBuffer(expr);
sb.append(" in (");
for (int i = 0; i < constraints.length; i++) {
final Object constraint = constraints[i];
Object key;
if (constraint instanceof RolapMember) {
key = ((RolapMember)constraint).getSqlKey();
} else {
key = constraint;
}
final ColumnConstraint constraint = constraints[i];
Object key = constraint.getValue();
if (key == RolapUtil.sqlNullValue) {
continue;
}
if (notNullCount > 0) {
sb.append(", ");
}
++notNullCount;
sb.append(quoteValue(constraint));
sb.append(quoteValue(key));
}
sb.append(")");
if (notNullCount < constraints.length) {
Expand All @@ -488,7 +475,7 @@ public String createInExpr(String expr, Object[] constraints) {
case 1:
// Special case -- one not-null value, and null, for
// example "(x is null or x = 1)".
return "(" + expr + " = " + quoteValue(constraints[0]) +
return "(" + expr + " = " + quoteValue(constraints[0].getValue()) +
" or " + expr + " is null)";
default:
// Nulls and values, for example,
Expand Down
15 changes: 9 additions & 6 deletions src/main/mondrian/rolap/SqlMemberSource.java
Expand Up @@ -326,8 +326,9 @@ private RolapMember[] getMembers(Connection jdbcConnection) {

if ( limit > 0 && limit < ++nFetch ) {
// result limit exceeded, throw an exception
String msg = "SqlMemberSource.getMembers Fetch limit(" +limit +") exceeded; sql=[" + sql + "]";
throw new ResultLimitExceeded(msg);
String msg = MondrianResource.instance().
getMemberFetchLimitExceeded(new Long(limit));
throw new ResultLimitExceeded(msg);
}

int column = 0;
Expand Down Expand Up @@ -539,8 +540,9 @@ private List getMembersInLevel(RolapLevel level, Connection jdbcConnection,

if ( limit > 0 && limit < ++nFetch ) {
// result limit exceeded, throw an exception
String msg = "SqlMemberSource.getMembersInLevel Fetch limit(" +limit +") exceeded; sql=[" + sql + "]";
throw new ResultLimitExceeded(msg);
String msg = MondrianResource.instance().
getMemberFetchLimitExceeded(new Long(limit));
throw new ResultLimitExceeded(msg);
}

int column = 0;
Expand Down Expand Up @@ -742,8 +744,9 @@ private void getMemberChildren(RolapMember parentMember, List children,

if ( limit > 0 && limit < ++nFetch ) {
// result limit exceeded, throw an exception
String msg = "SqlMemberSource.getMemberChildren Fetch limit(" +limit +") exceeded; sql=[" + sql + "]";
throw new ResultLimitExceeded(msg);
String msg = MondrianResource.instance().
getMemberFetchLimitExceeded(new Long(limit));
throw new ResultLimitExceeded(msg);
}

Object value = resultSet.getObject(1);
Expand Down
33 changes: 12 additions & 21 deletions src/main/mondrian/rolap/agg/Aggregation.java
Expand Up @@ -12,11 +12,9 @@

package mondrian.rolap.agg;

import mondrian.olap.Evaluator;
import mondrian.olap.Member;
import mondrian.olap.SchemaReader;
import mondrian.olap.Util;
import mondrian.rolap.RolapMember;
import mondrian.rolap.RolapStar;
import mondrian.rolap.cache.CachePool;
import mondrian.rolap.sql.SqlQuery;
Expand Down Expand Up @@ -114,7 +112,7 @@ public Aggregation(RolapStar star, RolapStar.Column[] columns) {
* gender = unconstrained
*/
public synchronized void load(RolapStar.Measure[] measures,
Object[][] constraintses, Collection pinnedSegments) {
ColumnConstraint[][] constraintses, Collection pinnedSegments) {
Segment[] segments = new Segment[measures.length];
for (int i = 0; i < measures.length; i++) {
RolapStar.Measure measure = measures[i];
Expand All @@ -132,11 +130,10 @@ public synchronized void load(RolapStar.Measure[] measures,
* Drops constraints, where the list of values is close to the values which
* would be returned anyway.
**/
public synchronized Object[][] optimizeConstraints(
Object[][] constraintses, Evaluator evaluator) {
public synchronized ColumnConstraint[][] optimizeConstraints(ColumnConstraint[][] constraintses) {
final int MAXLEN_ORACLE = 1000;
Util.assertTrue(constraintses.length == columns.length);
Object[][] newConstraintses = (Object[][]) constraintses.clone();
ColumnConstraint[][] newConstraintses = (ColumnConstraint[][]) constraintses.clone();
double[] bloats = new double[columns.length];

// We want to handle the special case "drilldown" which occurs pretty often.
Expand All @@ -145,8 +142,8 @@ public synchronized Object[][] optimizeConstraints(
List potentialParents = new ArrayList();
for (int i = 0; i < constraintses.length; i++) {
if (constraintses[i] != null && constraintses[i].length == 1
&& constraintses[i][0] instanceof RolapMember)
potentialParents.add(constraintses[i][0]);
&& constraintses[i][0].isMember())
potentialParents.add(constraintses[i][0].getMember());
}

for (int i = 0; i < newConstraintses.length; i++) {
Expand All @@ -163,13 +160,14 @@ public synchronized Object[][] optimizeConstraints(
// more than one - check for children of same parent
Member parent = null;
for (int j = 0; j < newConstraintses[i].length; j++) {
if (!(newConstraintses[i][j] instanceof Member)) {
if (!(newConstraintses[i][j].isMember())) {
// should not occur - but
// we compute bloat by #constraints / column cardinality
parent = null;
bloats[i] = constraintLength / columns[i].getCardinality();
break;
} else {
Member m = (Member) newConstraintses[i][j];
Member m = newConstraintses[i][j].getMember();
if (j == 0) {
parent = m.getParentMember();
} else {
Expand All @@ -190,10 +188,8 @@ public synchronized Object[][] optimizeConstraints(
// for the drilldown case, the children will be in the cache
// - if not, forget this optimization.
int nChildren = -1;
if (evaluator != null) {
SchemaReader scr = evaluator.getSchemaReader();
nChildren = scr.getChildrenCountFromCache(parent);
}
SchemaReader scr = star.getSchema().getSchemaReader();
nChildren = scr.getChildrenCountFromCache(parent);

if (nChildren == -1) {
// nothing gotten from cache
Expand Down Expand Up @@ -328,7 +324,7 @@ public RolapStar getStar() {
public static class Axis {
RolapStar.Column column;

Object[] constraints; // null if no constraint
ColumnConstraint[] constraints; // null if no constraint

Object[] keys; // actual keys retrieved

Expand All @@ -339,12 +335,7 @@ boolean contains(Object key) {
return true;
}
for (int i = 0; i < constraints.length; i++) {
if (constraints[i] instanceof RolapMember
&& ((RolapMember) constraints[i]).getSqlKey().equals(
key)) {
return true;
}
if (constraints[i].equals(key)) {
if (constraints[i].getValue().equals(key)) {
return true;
}
}
Expand Down

0 comments on commit d41d8cb

Please sign in to comment.