blob: 64cf736a212449aa205998736df50d5e94fec0a6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.calcite.materialize;
import org.apache.calcite.util.Util;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.pentaho.aggdes.algorithm.Algorithm;
import org.pentaho.aggdes.algorithm.Progress;
import org.pentaho.aggdes.algorithm.Result;
import org.pentaho.aggdes.algorithm.impl.MonteCarloAlgorithm;
import org.pentaho.aggdes.algorithm.util.ArgumentUtils;
import org.pentaho.aggdes.model.Aggregate;
import org.pentaho.aggdes.model.Attribute;
import org.pentaho.aggdes.model.Dialect;
import org.pentaho.aggdes.model.Dimension;
import org.pentaho.aggdes.model.Measure;
import org.pentaho.aggdes.model.Parameter;
import org.pentaho.aggdes.model.Schema;
import org.pentaho.aggdes.model.StatisticsProvider;
import org.pentaho.aggdes.model.Table;
import java.io.PrintWriter;
import java.util.List;
/**
* Algorithm that suggests a set of initial tiles (materialized aggregate views)
* for a given lattice.
*/
public class TileSuggester {
private final Lattice lattice;
public TileSuggester(Lattice lattice) {
this.lattice = lattice;
}
public Iterable<? extends Lattice.Tile> tiles() {
final Algorithm algorithm = new MonteCarloAlgorithm();
final PrintWriter pw = Util.printWriter(System.out);
final Progress progress = new ArgumentUtils.TextProgress(pw);
final StatisticsProvider statisticsProvider =
new StatisticsProviderImpl(lattice);
final double f = statisticsProvider.getFactRowCount();
final ImmutableMap.Builder<Parameter, Object> map = ImmutableMap.builder();
if (lattice.algorithmMaxMillis >= 0) {
map.put(Algorithm.ParameterEnum.timeLimitSeconds,
Math.max(1, (int) (lattice.algorithmMaxMillis / 1000L)));
}
map.put(Algorithm.ParameterEnum.aggregateLimit, 3);
map.put(Algorithm.ParameterEnum.costLimit, f * 5d);
final SchemaImpl schema = new SchemaImpl(lattice, statisticsProvider);
final Result result = algorithm.run(schema, map.build(), progress);
final ImmutableList.Builder<Lattice.Tile> tiles = ImmutableList.builder();
for (Aggregate aggregate : result.getAggregates()) {
tiles.add(toTile(aggregate));
}
return tiles.build();
}
private Lattice.Tile toTile(Aggregate aggregate) {
final Lattice.TileBuilder tileBuilder = new Lattice.TileBuilder();
for (Lattice.Measure measure : lattice.defaultMeasures) {
tileBuilder.addMeasure(measure);
}
for (Attribute attribute : aggregate.getAttributes()) {
tileBuilder.addDimension(((AttributeImpl) attribute).column);
}
return tileBuilder.build();
}
/** Implementation of {@link Schema} based on a {@link Lattice}. */
private static class SchemaImpl implements Schema {
private final StatisticsProvider statisticsProvider;
private final TableImpl table;
private final ImmutableList<AttributeImpl> attributes;
SchemaImpl(Lattice lattice, StatisticsProvider statisticsProvider) {
this.statisticsProvider = statisticsProvider;
this.table = new TableImpl();
final ImmutableList.Builder<AttributeImpl> attributeBuilder =
ImmutableList.builder();
for (Lattice.Column column : lattice.columns) {
attributeBuilder.add(new AttributeImpl(column, table));
}
this.attributes = attributeBuilder.build();
}
public List<? extends Table> getTables() {
return ImmutableList.of(table);
}
public List<Measure> getMeasures() {
throw new UnsupportedOperationException();
}
public List<? extends Dimension> getDimensions() {
throw new UnsupportedOperationException();
}
public List<? extends Attribute> getAttributes() {
return attributes;
}
public StatisticsProvider getStatisticsProvider() {
return statisticsProvider;
}
public Dialect getDialect() {
throw new UnsupportedOperationException();
}
public String generateAggregateSql(Aggregate aggregate,
List<String> columnNameList) {
throw new UnsupportedOperationException();
}
}
/** Implementation of {@link Table} based on a {@link Lattice}.
* There is only one table (in this sense of table) in a lattice.
* The algorithm does not really care about tables. */
private static class TableImpl implements Table {
public String getLabel() {
return "TABLE";
}
public Table getParent() {
return null;
}
}
/** Implementation of {@link Attribute} based on a {@link Lattice.Column}. */
private static class AttributeImpl implements Attribute {
private final Lattice.Column column;
private final TableImpl table;
private AttributeImpl(Lattice.Column column, TableImpl table) {
this.column = column;
this.table = table;
}
@Override public String toString() {
return getLabel();
}
public String getLabel() {
return column.alias;
}
public Table getTable() {
return table;
}
public double estimateSpace() {
return 0;
}
public String getCandidateColumnName() {
return null;
}
public String getDatatype(Dialect dialect) {
return null;
}
public List<Attribute> getAncestorAttributes() {
return ImmutableList.of();
}
}
/** Implementation of {@link org.pentaho.aggdes.model.StatisticsProvider}
* that asks the lattice. */
private static class StatisticsProviderImpl implements StatisticsProvider {
private final Lattice lattice;
StatisticsProviderImpl(Lattice lattice) {
this.lattice = lattice;
}
public double getFactRowCount() {
return lattice.getFactRowCount();
}
public double getRowCount(List<Attribute> attributes) {
return lattice.getRowCount(
Util.transform(attributes, input -> ((AttributeImpl) input).column));
}
public double getSpace(List<Attribute> attributes) {
return attributes.size();
}
public double getLoadTime(List<Attribute> attributes) {
return getSpace(attributes) * getRowCount(attributes);
}
}
}
// End TileSuggester.java