Skip to content

Commit

Permalink
IGNITE-17190 Move ignite query statistics to core, fix SQL ANALYZE co…
Browse files Browse the repository at this point in the history
…mmand (apache#10175)
  • Loading branch information
ivandasch authored Aug 19, 2022
1 parent 2361ff3 commit 5b62a8b
Show file tree
Hide file tree
Showing 90 changed files with 1,374 additions and 1,034 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,10 @@
package org.apache.ignite.internal.processors.query.calcite.metadata;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.plan.volcano.RelSubset;
import org.apache.calcite.rel.RelNode;
Expand Down Expand Up @@ -60,7 +58,6 @@
import org.apache.ignite.internal.processors.query.calcite.schema.IgniteTable;
import org.apache.ignite.internal.processors.query.calcite.util.RexUtils;
import org.apache.ignite.internal.processors.query.stat.ColumnStatistics;
import org.h2.value.Value;
import org.jetbrains.annotations.Nullable;

/** */
Expand Down Expand Up @@ -167,74 +164,6 @@ private BigDecimal toComparableValue(RexLiteral val) {
return null;
}

/**
* Convert specified value into comparable type: BigDecimal,
*
* @param val Value to convert to comparable form.
* @return Comparable form of value.
*/
private BigDecimal toComparableValue(Value val) {
if (val == null)
return null;

switch (val.getType()) {
case Value.NULL:
throw new IllegalArgumentException("Can't compare null values");

case Value.BOOLEAN:
return (val.getBoolean()) ? BigDecimal.ONE : BigDecimal.ZERO;

case Value.BYTE:
return new BigDecimal(val.getByte());

case Value.SHORT:
return new BigDecimal(val.getShort());

case Value.INT:
return new BigDecimal(val.getInt());

case Value.LONG:
return new BigDecimal(val.getLong());

case Value.DECIMAL:
return val.getBigDecimal();

case Value.DOUBLE:
return BigDecimal.valueOf(val.getDouble());

case Value.FLOAT:
return BigDecimal.valueOf(val.getFloat());

case Value.DATE:
return BigDecimal.valueOf(val.getDate().getTime());

case Value.TIME:
return BigDecimal.valueOf(val.getTime().getTime());

case Value.TIMESTAMP:
return BigDecimal.valueOf(val.getTimestamp().getTime());

case Value.BYTES:
BigInteger bigInteger = new BigInteger(1, val.getBytes());
return new BigDecimal(bigInteger);

case Value.STRING:
case Value.STRING_FIXED:
case Value.STRING_IGNORECASE:
case Value.ARRAY:
case Value.JAVA_OBJECT:
case Value.GEOMETRY:
return null;

case Value.UUID:
BigInteger bigInt = new BigInteger(1, val.getBytes());
return new BigDecimal(bigInt);

default:
throw new IllegalStateException("Unsupported H2 type: " + val.getType());
}
}

/**
* Predicate based selectivity for table. Estimate condition on each column taking in comparison it's statistics.
*
Expand Down Expand Up @@ -395,16 +324,20 @@ private double estimateRefSelectivity(ProjectableFilterableTableScan rel, RelMet
ColumnStatistics colStat = getColumnStatistics(mq, rel, ref);
double res = 0.33;

if (colStat == null) {
if (colStat == null || colStat.max() == null || colStat.min() == null) {
// true, false and null with equivalent probability
return res;
}

if (colStat.max() == null || colStat.max().getType() != Value.BOOLEAN)
// Check whether it can be considered as BOOL.
boolean isBool = (colStat.max().compareTo(BigDecimal.ONE) == 0 || colStat.max().compareTo(BigDecimal.ZERO) == 0)
&& (colStat.min().compareTo(BigDecimal.ONE) == 0 || colStat.min().compareTo(BigDecimal.ZERO) == 0);

if (!isBool)
return res;

Boolean min = colStat.min().getBoolean();
Boolean max = colStat.max().getBoolean();
Boolean min = colStat.min().compareTo(BigDecimal.ONE) == 0;
Boolean max = colStat.max().compareTo(BigDecimal.ONE) == 0;

if (!max)
return 0;
Expand Down Expand Up @@ -450,8 +383,8 @@ private double estimateSelectivity(ColumnStatistics colStat, BigDecimal val, Rex

SqlOperator op = ((RexCall)pred).op;

BigDecimal min = toComparableValue(colStat.min());
BigDecimal max = toComparableValue(colStat.max());
BigDecimal min = colStat.min();
BigDecimal max = colStat.max();
BigDecimal total = (min == null || max == null) ? null : max.subtract(min).abs();

if (total == null)
Expand Down Expand Up @@ -537,13 +470,13 @@ private double estimateEqualsSelectivity(ColumnStatistics colStat, RexCall pred)
return guessSelectivity(pred);

if (colStat.min() != null) {
BigDecimal minComparable = toComparableValue(colStat.min());
BigDecimal minComparable = colStat.min();
if (minComparable != null && minComparable.compareTo(comparableVal) > 0)
return 0.;
}

if (colStat.max() != null) {
BigDecimal maxComparable = toComparableValue(colStat.max());
BigDecimal maxComparable = colStat.max();
if (maxComparable != null && maxComparable.compareTo(comparableVal) < 0)
return 0.;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
package org.apache.ignite.internal.processors.query.calcite.prepare;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.cache.query.index.Index;
import org.apache.ignite.internal.processors.cache.GridCacheContextInfo;
import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
import org.apache.ignite.internal.processors.query.QueryField;
import org.apache.ignite.internal.processors.query.calcite.util.AbstractService;
import org.apache.ignite.internal.processors.query.schema.SchemaChangeListener;
import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
Expand Down Expand Up @@ -100,7 +102,11 @@ public void subscriptionProcessor(GridInternalSubscriptionProcessor subscription
}

/** {@inheritDoc} */
@Override public void onSqlTypeDropped(String schemaName, GridQueryTypeDescriptor typeDescriptor) {
@Override public void onSqlTypeDropped(
String schemaName,
GridQueryTypeDescriptor typeDescriptor,
boolean destroy
) {
clear();
}

Expand Down Expand Up @@ -140,8 +146,22 @@ public void subscriptionProcessor(GridInternalSubscriptionProcessor subscription
}

/** {@inheritDoc} */
@Override public void onSqlTypeUpdated(String schemaName, GridQueryTypeDescriptor typeDesc,
GridCacheContextInfo<?, ?> cacheInfo) {
@Override public void onColumnsAdded(
String schemaName,
GridQueryTypeDescriptor typeDesc,
GridCacheContextInfo<?, ?> cacheInfo,
List<QueryField> cols
) {
clear();
}

/** {@inheritDoc} */
@Override public void onColumnsDropped(
String schemaName,
GridQueryTypeDescriptor typeDesc,
GridCacheContextInfo<?, ?> cacheInfo,
List<String> cols
) {
clear();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.apache.ignite.internal.processors.cache.GridCacheContextInfo;
import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
import org.apache.ignite.internal.processors.query.QueryField;
import org.apache.ignite.internal.processors.query.calcite.exec.exp.IgniteScalarFunction;
import org.apache.ignite.internal.processors.query.calcite.trait.TraitUtils;
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
Expand Down Expand Up @@ -188,10 +189,21 @@ public void subscriptionProcessor(GridInternalSubscriptionProcessor subscription
}

/** {@inheritDoc} */
@Override public void onSqlTypeUpdated(
@Override public void onColumnsAdded(
String schemaName,
GridQueryTypeDescriptor typeDesc,
GridCacheContextInfo<?, ?> cacheInfo
GridCacheContextInfo<?, ?> cacheInfo,
List<QueryField> cols
) {
onSqlTypeCreated(schemaName, typeDesc, cacheInfo);
}

/** {@inheritDoc} */
@Override public void onColumnsDropped(
String schemaName,
GridQueryTypeDescriptor typeDesc,
GridCacheContextInfo<?, ?> cacheInfo,
List<String> cols
) {
onSqlTypeCreated(schemaName, typeDesc, cacheInfo);
}
Expand All @@ -206,7 +218,8 @@ private static Object affinityIdentity(CacheConfiguration<?, ?> ccfg) {
/** {@inheritDoc} */
@Override public synchronized void onSqlTypeDropped(
String schemaName,
GridQueryTypeDescriptor typeDesc
GridQueryTypeDescriptor typeDesc,
boolean destroy
) {
IgniteSchema schema = igniteSchemas.computeIfAbsent(schemaName, IgniteSchema::new);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,11 @@
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeSystem;
import org.apache.ignite.internal.processors.query.stat.ColumnStatistics;
import org.apache.ignite.internal.processors.query.stat.ObjectStatisticsImpl;
import org.h2.value.ValueBoolean;
import org.h2.value.ValueByte;
import org.h2.value.ValueDate;
import org.h2.value.ValueDouble;
import org.h2.value.ValueFloat;
import org.h2.value.ValueInt;
import org.h2.value.ValueLong;
import org.h2.value.ValueShort;
import org.h2.value.ValueString;
import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
import org.junit.Before;
import org.junit.Test;

import static org.apache.ignite.internal.processors.query.stat.StatisticsUtils.toDecimal;

/**
* Statistic related simple tests.
*/
Expand Down Expand Up @@ -150,40 +141,35 @@ public class StatisticsPlannerTest extends AbstractPlannerTest {
tbl4.addIndex("TBL4_SHORT_LONG", 6, 7);

HashMap<String, ColumnStatistics> colStat1 = new HashMap<>();
colStat1.put("T1C1INT", new ColumnStatistics(ValueInt.get(1), ValueInt.get(1000),
0, 1000, t1rc, 4, null, 1, 0));
colStat1.put("T1C1INT", new ColumnStatistics(toDecimal(1), toDecimal(1000), 0, 1000, t1rc, 4, null, 1, 0));

colStat1.put("T1C2STR", new ColumnStatistics(ValueString.get("A1"), ValueString.get("Z9"),
100, 20, t1rc, 2, null, 1, 0));
colStat1.put("T1C2STR", new ColumnStatistics(null, null, 100, 20, t1rc, 2, null, 1, 0));

colStat1.put("T1C3DBL", new ColumnStatistics(ValueDouble.get(0.01), ValueDouble.get(0.99),
10, 1000, t1rc, 8, null, 1, 0));
colStat1.put("T1C3DBL", new ColumnStatistics(toDecimal(0.01), toDecimal(0.99), 10, 1000, t1rc, 8, null, 1, 0));

colStat1.put("T1C4BYTE", new ColumnStatistics(ValueByte.get((byte)0), ValueByte.get((byte)255),
10, 1000, t1rc, 8, null, 1, 0));
colStat1.put("T1C4BYTE", new ColumnStatistics(toDecimal((byte)0), toDecimal((byte)255), 10, 1000, t1rc, 8, null,
1, 0));

colStat1.put("T1C5BOOLEAN", new ColumnStatistics(ValueBoolean.get(false), ValueBoolean.get(true),
0, 2, t1rc, 1, null, 1, 0));
colStat1.put("T1C5BOOLEAN", new ColumnStatistics(toDecimal(false), toDecimal(true), 0, 2, t1rc, 1, null, 1, 0));

colStat1.put("T1C6CHARACTER", new ColumnStatistics(ValueString.get("A"), ValueString.get("Z"),
10, 10, t1rc, 1, null, 1, 0));
colStat1.put("T1C6CHARACTER", new ColumnStatistics(null, null, 10, 10, t1rc, 1, null, 1, 0));

colStat1.put("T1C7SHORT", new ColumnStatistics(ValueShort.get((short)1), ValueShort.get((short)5000),
colStat1.put("T1C7SHORT", new ColumnStatistics(toDecimal((short)1), toDecimal((short)5000),
110, 500, t1rc, 2, null, 1, 0));

colStat1.put("T1C8LONG", new ColumnStatistics(ValueLong.get(1L), ValueLong.get(100000L),
colStat1.put("T1C8LONG", new ColumnStatistics(toDecimal(1L), toDecimal(100000L),
10, 100000, t1rc, 8, null, 1, 0));

colStat1.put("T1C9FLOAT", new ColumnStatistics(ValueFloat.get((float)0.1), ValueFloat.get((float)0.9),
colStat1.put("T1C9FLOAT", new ColumnStatistics(toDecimal((float)0.1), toDecimal((float)0.9),
10, 1000, t1rc, 8, null, 1, 0));

colStat1.put("T1C10DATE", new ColumnStatistics(ValueDate.get(MIN_DATE), ValueDate.get(MAX_DATE),
colStat1.put("T1C10DATE", new ColumnStatistics(toDecimal(MIN_DATE), toDecimal(MAX_DATE),
20, 1000, t1rc, 8, null, 1, 0));

colStat1.put("T1C11TIME", new ColumnStatistics(ValueTime.get(MIN_TIME), ValueTime.get(MAX_TIME),
colStat1.put("T1C11TIME", new ColumnStatistics(toDecimal(MIN_TIME), toDecimal(MAX_TIME),
10, 1000, t1rc, 8, null, 1, 0));

colStat1.put("T1C12TIMESTAMP", new ColumnStatistics(ValueTimestamp.get(MIN_TIMESTAMP), ValueTimestamp.get(MAX_TIMESTAMP),
colStat1.put("T1C12TIMESTAMP", new ColumnStatistics(toDecimal(MIN_TIMESTAMP), toDecimal(MAX_TIMESTAMP),
20, 1000, t1rc, 8, null, 1, 0));

tbl1stat = new IgniteStatisticsImpl(new ObjectStatisticsImpl(1000, colStat1));
Expand Down Expand Up @@ -437,10 +423,9 @@ public void testIndexWithBetterSelectivityPreferred() throws Exception {
int rowCnt = 10_000;

HashMap<String, ColumnStatistics> colStat1 = new HashMap<>();
colStat1.put("T1C2STR", new ColumnStatistics(ValueString.get("A1"), ValueString.get("Z9"),
0, 1, rowCnt, 2, null, 1, 0));
colStat1.put("T1C2STR", new ColumnStatistics(null, null, 0, 1, rowCnt, 2, null, 1, 0));

colStat1.put("T1C7SHORT", new ColumnStatistics(ValueShort.get((short)1), ValueShort.get((short)5000),
colStat1.put("T1C7SHORT", new ColumnStatistics(toDecimal((short)1), toDecimal((short)5000),
0, rowCnt, rowCnt, 2, null, 1, 0));

IgniteStatisticsImpl stat = new IgniteStatisticsImpl(new ObjectStatisticsImpl(1000, colStat1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,10 @@ public static void main(String[] args) throws Exception {
gen.generateAndWrite(SqlTableColumnView.class, INDEXING_SRC_DIR);
gen.generateAndWrite(SqlViewColumnView.class, INDEXING_SRC_DIR);

gen.generateAndWrite(StatisticsColumnConfigurationView.class, INDEXING_SRC_DIR);
gen.generateAndWrite(StatisticsColumnLocalDataView.class, INDEXING_SRC_DIR);
gen.generateAndWrite(StatisticsColumnGlobalDataView.class, INDEXING_SRC_DIR);
gen.generateAndWrite(StatisticsColumnPartitionDataView.class, INDEXING_SRC_DIR);
gen.generateAndWrite(StatisticsColumnConfigurationView.class, DFLT_SRC_DIR);
gen.generateAndWrite(StatisticsColumnLocalDataView.class, DFLT_SRC_DIR);
gen.generateAndWrite(StatisticsColumnGlobalDataView.class, DFLT_SRC_DIR);
gen.generateAndWrite(StatisticsColumnPartitionDataView.class, DFLT_SRC_DIR);
}

/**
Expand Down
Loading

0 comments on commit 5b62a8b

Please sign in to comment.